## 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`)** | 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: 1. Podstawowy plik `appsettings.json`. 2. Plik środowiskowy, np. `appsettings.Development.json` lub `appsettings.Production.json`. 3. Zmienne środowiskowe (Environment Variables) systemu operacyjnego, które zawsze nadpisują wartości z plików JSON. 4. 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 ``. ```json { "Logging": { "LogLevel": { "Default": "Information", "Microsoft.AspNetCore": "Warning" } }, "SystemSettings": { "FeatureToggle": true, "MaxRetryAttempts": 3 } } ``` **2. Klasa Opcji (POCO):** Obiekt modelujący ustawienia biznesowe. ```csharp 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. ```csharp using ModernApp.Configuration; var builder = WebApplication.CreateBuilder(args); // Rejestracja sekcji JSON i wstrzyknięcie jako IOptions builder.Services.Configure( 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`. ```csharp // 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 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.