7.5 KiB
Wstęp merytoryczny: Ewolucja zarządzania konfiguracją w ekosystemie .NET
W procesie transformacji aplikacji desktopowych z .NET Framework 4.8 do nowoczesnego środowiska .NET 10, zmianie ulega nie tylko sposób renderowania interfejsu, ale również mechanika zarządzania ustawieniami aplikacji. W starym modelu architektonicznym parametry konfiguracyjne przechowywano w ciężkich, płaskich plikach XML (App.config dla WPF/WinForms lub Web.config), z których odczytywano je najczęściej za pomocą statycznej klasy ConfigurationManager.
W ASP.NET Core oraz nowym modelu uruchomieniowym odpowiedzialność za konfigurację przejmuje Generic Host (Host Ogólny). Infrastruktura Hosta domyślnie ładuje i agreguje ustawienia z wielu źródeł, w tym przede wszystkim z nowoczesnego, hierarchicznego pliku appsettings.json. Podejście to całkowicie rezygnuje ze statycznego, globalnego dostępu do stanu aplikacji na rzecz wbudowanego wstrzykiwania zależności (DI).
Analiza Porównawcza: Zarządzanie ustawieniami (Desktop 4.8 vs Web .NET 10)
| Koncepcja Desktop (.NET 4.8) | Odpowiednik w .NET 10 (Generic Host) | Charakter zmiany architektonicznej |
|---|---|---|
Plik App.config / Web.config (XML) |
Plik appsettings.json (JSON) |
Przejście z płaskich struktur XML z atrybutami, na elastyczne i czytelne struktury hierarchiczne (zagnieżdżone obiekty JSON). |
Statyczna klasa ConfigurationManager |
Interfejs IConfiguration i Kontener DI |
Wyeliminowanie wzorca Service Locator oraz globalnego stanu na rzecz wstrzykiwania zależności, ściśle zarządzanego przez Generic Host. |
| Brak wbudowanych profili środowiskowych | appsettings.Development.json / Zmienne Środowiskowe |
Host automatycznie podmienia wartości konfiguracji bazując na aktywnym środowisku (np. Development, Production) bez potrzeby stosowania transformacji XML. |
Ręczne rzutowanie typów (int.Parse) |
Options Pattern (IOptions<T>) |
Automatyczne mapowanie sekcji plików JSON na silnie typowane klasy (POCO), wstrzykiwane bezpośrednio do logiki biznesowej. |
Głębokie Nurkowanie (Deep Dive): Integracja konfiguracji z Generic Host
W architekturze ASP.NET Core, plik appsettings.json nie jest samodzielnym bytem, lecz integralną częścią procesu budowania Hosta. Gdy w pliku startowym wywołujemy konstrukcję WebApplication.CreateBuilder(args), Generic Host pod spodem konfiguruje całą infrastrukturę ładowania ustawień.
Proces ten odbywa się warstwowo. Host odczytuje konfigurację z określonego łańcucha dostawców (Configuration Providers) w ustalonej kolejności:
- Podstawowy plik
appsettings.json. - Plik środowiskowy, np.
appsettings.Development.jsonlubappsettings.Production.json. - Zmienne środowiskowe (Environment Variables) systemu operacyjnego, które zawsze nadpisują wartości z plików JSON.
- Argumenty wiersza poleceń.
Dzięki temu system jest naturalnie przystosowany do orkiestracji kontenerów (np. Docker, Kubernetes), w których zmienne środowiskowe sterują zachowaniem Hosta bez konieczności re-kompilacji aplikacji czy podmiany plików konfiguracyjnych.
Architektura systemowa: Wzorzec Opcji (Options Pattern)
Bezpośrednie używanie interfejsu IConfiguration w klasach biznesowych, polegające na odpytywaniu go ciągami znaków (np. config["Smtp:Port"]), jest w nowoczesnym .NET antywzorcem prowadzącym do tzw. magic strings.
Zamiast tego, framework promuje użycie Options Pattern. Architektura ta polega na stworzeniu klasy C# idealnie odzwierciedlającej strukturę wycinka pliku appsettings.json. Następnie, za pomocą kontenera usług Hosta (DI), wiążemy (bindujemy) sekcję pliku JSON z tą klasą. Wymusza to silne typowanie konfiguracji w całym rurociągu żądań HTTP i eliminuje rozproszenie danych aplikacyjnych.
Dobre Praktyki i Antywzorce
Proces migracji wymusza rewizję dawnych nawyków konfiguracji środowisk deweloperskich i produkcyjnych:
- Antywzorzec: Przechowywanie tajemnic w
appsettings.json. Przechowywanie kluczy do zewnętrznych API, haseł do bazy danych czy certyfikatów produkcyjnych jawnym tekstem w konfiguracji zapisanej w repozytorium źródłowym. - Dobra praktyka: Parametry połączeń (Connection Strings) na maszynie programisty należy umieszczać w specjalnym lokalnym mechanizmie wbudowanym w Hosta – Secret Manager (User Secrets). Na docelowym środowisku produkcyjnym korzystamy natomiast z usług do bezpiecznego przechowywania tajemnic, np. Azure Key Vault. Generic Host automatycznie podepnie te źródła jako bezpieczne nadpisania dla pliku konfiguracyjnego.
Laboratorium kodu: Konfiguracja i Wzorzec Opcji
Poniższe bloki demonstrują prawidłową konfigurację w .NET 10, która na etapie startu Hosta wiąże właściwości z sekcją pliku JSON, wstrzykując je jako silnie typowaną klasę do logiki aplikacji.
1. Plik appsettings.json:
Hierarchiczna struktura zastępująca zawiłe bloki znane z dawnego <appSettings>.
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"SystemSettings": {
"FeatureToggle": true,
"MaxRetryAttempts": 3
}
}
2. Klasa Opcji (POCO): Obiekt modelujący ustawienia biznesowe.
namespace ModernApp.Configuration;
public class SystemSettingsOptions
{
// Konwencja nazewnicza ściśle odpowiada polom z pliku JSON
public bool FeatureToggle { get; set; }
public int MaxRetryAttempts { get; set; }
}
3. Inicjalizacja Hosta (Program.cs):
Rejestracja opcji bezpośrednio z poziomu kontenera DI budowniczego. Wzorzec ten izoluje IConfiguration tylko do momentu startu aplikacji.
using ModernApp.Configuration;
var builder = WebApplication.CreateBuilder(args);
// Rejestracja sekcji JSON i wstrzyknięcie jako IOptions<SystemSettingsOptions>
builder.Services.Configure<SystemSettingsOptions>(
builder.Configuration.GetSection("SystemSettings"));
builder.Services.AddRazorComponents()
.AddInteractiveServerComponents();
var app = builder.Build();
// (Rurociąg Middleware...)
app.Run();
4. Wykorzystanie w serwisie lub komponencie Blazor:
Logika biznesowa otrzymuje gotowy obiekt przy użyciu IOptions<T>.
// SystemService.cs - rejestrowany w DI
using Microsoft.Extensions.Options;
public class SystemService
{
private readonly SystemSettingsOptions _settings;
// Klasyczne, poprawne wstrzykiwanie w architekturze .NET 10
public SystemService(IOptions<SystemSettingsOptions> options)
{
_settings = options.Value;
}
public void PerformOperation()
{
if (_settings.FeatureToggle)
{
// Nowa funkcjonalność uruchomiona z konfiguracji Hosta
for (int i = 0; i < _settings.MaxRetryAttempts; i++) { /*...*/ }
}
}
}
Wnioski architektoniczne
Porzucenie pliku App.config i interfejsów systemu Windows na rzecz Generic Hosta przetwarzającego appsettings.json to milowy krok w kierunku budowania skalowalnych i bezpiecznych aplikacji rozproszonych. W środowisku .NET 10 konfiguracja jest mechanizmem odseparowanym, który naturalnie współpracuje z kontenerem Dependency Injection oraz systemami wdrażania (CI/CD). Programiści, zamiast siłować się z wczytywaniem i parsowaniem typów prostych (często rzucającymi wyjątkami podczas startu), mogą swobodnie pracować w warstwach biznesowych z użyciem walidowanych i bezstanowych klas wzorca Options, nad którymi pieczę operacyjną sprawuje potok uruchomieniowy.