C# Academy · Lekcja

Silnie typowane opcje z IOptions

Powiąż sekcje konfiguracji z klasami POCO za pomocą IOptions , IOptionsSnapshot i IOptionsMonitor .

Lekcja 2 z 412 kroki

Silnie typowane opcje z IOptions to bezpłatna lekcja C# Academy na CoddyKit. To lekcja 2 z 4. Możesz przeczytać całą lekcję poniżej za darmo — a potem ćwiczyć ją interaktywnie w przeglądarce z wbudowanym edytorem kodu i tutorem AI dostępnym 24/7. To część ścieżki edukacyjnej C# Academy, a Twój postęp synchronizuje się między webem a aplikacją CoddyKit. Kurs C# Academy zawiera 4 lekcji w sumie.

Dlaczego warto używać silnie typowanych opcji?

Odczyt konfiguracji za pomocą IConfiguration["Key"] zwraca niejawnie typowane ciągi znaków. Wzorzec Options mapuje sekcje konfiguracji na klasy C#, zapewniając bezpieczeństwo na etapie kompilacji, funkcję IntelliSense i obsługę walidacji.

Definiowanie klasy opcji

Utwórz zwykłą klasę POCO, której nazwy właściwości odpowiadają kluczom JSON. Zgodnie z konwencją dodaj statyczną stałą SectionName, która identyfikuje sekcję konfiguracji.

// Configuration class
public class JwtOptions
{
    public const string SectionName = "Jwt";

    public string SecretKey { get; set; } = string.Empty;
    public string Issuer    { get; set; } = string.Empty;
    public string Audience  { get; set; } = string.Empty;
    public int    ExpiryMinutes { get; set; } = 60;
}

// appsettings.json:
{
  "Jwt": {
    "SecretKey": "my-very-secret-key",
    "Issuer": "https://myapp.com",
    "Audience": "https://myapp.com/api",
    "ExpiryMinutes": 120
  }
}

Rejestrowanie opcji

Wywołaj Configure<T>, aby powiązać sekcję konfiguracji z klasą opcji. Spowoduje to zarejestrowanie IOptions<T>, IOptionsSnapshot<T> i IOptionsMonitor<T> w DI.

// Registration
builder.Services.Configure<JwtOptions>(
    builder.Configuration.GetSection(JwtOptions.SectionName));

// Alternative shorthand:
builder.Services
    .AddOptions<JwtOptions>()
    .BindConfiguration(JwtOptions.SectionName);

// Consuming via IOptions<T>:
public class TokenService
{
    private readonly JwtOptions _opts;

    public TokenService(IOptions<JwtOptions> opts)
        => _opts = opts.Value;

    public string CreateToken()
        => $"Issuer={_opts.Issuer}, Exp={_opts.ExpiryMinutes}m";
}

IOptions a IOptionsSnapshot a IOptionsMonitor

Istnieją trzy warianty o różnym czasie życia i różnym zachowaniu podczas ponownego ładowania. Wybierz właściwy wariant do danego zastosowania.

// IOptions<T> — Singleton, reads config ONCE at startup
public class ApiClient(IOptions<ApiOptions> opts)
{
    private readonly ApiOptions _opts = opts.Value; // never changes
}

// IOptionsSnapshot<T> — Scoped, reloads per request
public class ReportService(IOptionsSnapshot<ReportOptions> opts)
{
    private readonly ReportOptions _opts = opts.Value; // fresh per request
}

// IOptionsMonitor<T> — Singleton, live updates + change notifications
public class FeatureService(IOptionsMonitor<FeatureFlags> monitor)
{
    public bool IsEnabled(string feature)
        => monitor.CurrentValue.EnabledFeatures.Contains(feature);
}

Walidacja opcji za pomocą atrybutów

Oznacz właściwości opcji atrybutami z System.ComponentModel.DataAnnotations i wywołaj ValidateDataAnnotations(), aby natychmiast wykrywać nieprawidłową konfigurację podczas uruchamiania.

using System.ComponentModel.DataAnnotations;

public class SmtpOptions
{
    [Required]
    public string Host { get; set; } = string.Empty;

    [Range(1, 65535)]
    public int Port { get; set; } = 587;

    [Required, EmailAddress]
    public string FromAddress { get; set; } = string.Empty;
}

// Register with validation:
builder.Services
    .AddOptions<SmtpOptions>()
    .BindConfiguration("Smtp")
    .ValidateDataAnnotations()
    .ValidateOnStart(); // fail at startup, not first use

Niestandardowa walidacja za pomocą IValidateOptions

W przypadku złożonych reguł dotyczących wielu właściwości zaimplementuj IValidateOptions<T>, aby uzyskać pełną programową logikę walidacji.

public class JwtOptionsValidator : IValidateOptions<JwtOptions>
{
    public ValidateOptionsResult Validate(string? name, JwtOptions opts)
    {
        var errors = new List<string>();

        if (string.IsNullOrWhiteSpace(opts.SecretKey))
            errors.Add("SecretKey must not be empty");

        if (opts.SecretKey.Length < 32)
            errors.Add("SecretKey must be at least 32 characters");

        if (opts.ExpiryMinutes <= 0)
            errors.Add("ExpiryMinutes must be positive");

        return errors.Any()
            ? ValidateOptionsResult.Fail(errors)
            : ValidateOptionsResult.Success;
    }
}

builder.Services.AddSingleton<IValidateOptions<JwtOptions>, JwtOptionsValidator>();

Post-Configure

PostConfigure jest wykonywane po wszystkich wywołaniach Configure i umożliwia nadpisywanie lub wyprowadzanie wartości — jest przydatne w przypadku właściwości obliczanych albo dostosowań zależnych od środowiska.

builder.Services.Configure<CacheOptions>(
    builder.Configuration.GetSection("Cache"));

// Override in test environment:
builder.Services.PostConfigure<CacheOptions>(opts =>
{
    if (builder.Environment.IsEnvironment("Testing"))
    {
        opts.AbsoluteExpirationMinutes = 1; // very short in tests
        opts.UseDistributedCache = false;   // use in-memory cache
    }
});

// PostConfigure always runs LAST, even after AddOptions validators

Opcje nazwane

Jeśli potrzebujesz wielu instancji tego samego typu opcji, na przykład dwóch serwerów SMTP, użyj opcji nazwanych, aby je rozróżnić.

// Register named options:
builder.Services.Configure<SmtpOptions>("Primary",
    builder.Configuration.GetSection("Smtp:Primary"));
builder.Services.Configure<SmtpOptions>("Backup",
    builder.Configuration.GetSection("Smtp:Backup"));

// Consume with IOptionsMonitor (supports named options):
public class EmailSender
{
    private readonly SmtpOptions _primary;
    private readonly SmtpOptions _backup;

    public EmailSender(IOptionsMonitor<SmtpOptions> monitor)
    {
        _primary = monitor.Get("Primary");
        _backup  = monitor.Get("Backup");
    }
}

Skrócona forma BindConfiguration

Łańcuch AddOptions().BindConfiguration() to nowoczesny, płynny sposób na zarejestrowanie, powiązanie, zwalidowanie i natychmiastowe odrzucenie nieprawidłowej konfiguracji w jednym wyrażeniu.

// Full registration chain:
builder.Services
    .AddOptions<DatabaseOptions>()
    .BindConfiguration("Database")          // bind section
    .ValidateDataAnnotations()               // attribute validation
    .Validate(opts =>                        // custom rule
        opts.MaxPoolSize >= opts.MinPoolSize,
        "MaxPoolSize must be >= MinPoolSize")
    .ValidateOnStart();                      // fail at startup

// Shorthand for simple cases:
builder.Services.AddOptions<AppOptions>()
    .BindConfiguration(AppOptions.SectionName)
    .ValidateOnStart();

Praktyczny przykład: opcje flag funkcji

Kompletna konfiguracja opcji flag funkcji z obsługą ponownego ładowania, umożliwiająca zmianę przełączników w appsettings bez ponownego wdrażania aplikacji.

public class FeatureFlags
{
    public bool EnableNewCheckout  { get; set; }
    public bool EnableAISearch     { get; set; }
    public bool EnableBetaDashboard { get; set; }
}

// appsettings.json:
// { "FeatureFlags": { "EnableNewCheckout": true, ... } }

builder.Services
    .AddOptions<FeatureFlags>()
    .BindConfiguration("FeatureFlags")
    .ValidateOnStart();

// In a controller or service:
public class CheckoutController : ControllerBase
{
    private readonly FeatureFlags _flags;

    public CheckoutController(IOptionsMonitor<FeatureFlags> m)
        => _flags = m.CurrentValue;

    [HttpGet("/checkout")]
    public IActionResult Index() =>
        _flags.EnableNewCheckout
            ? Ok("new checkout")
            : Ok("legacy checkout");
}

Szybkie sprawdzenie

Którego wariantu IOptions należy użyć w usłudze Singleton, która musi odzwierciedlać zmiany konfiguracji na żywo?

Podsumowanie: silnie typowane opcje z IOptions

Najważniejsze informacje:

  • Wzorzec Options wiąże sekcje konfiguracji z obiektami POCO za pomocą Configure<T> lub AddOptions<T>().BindConfiguration()
  • IOptions<T>: Singleton, odczytuje wartości raz podczas uruchamiania
  • IOptionsSnapshot<T>: Scoped, ponownie ładuje wartości dla każdego żądania — nie wstrzykuj go do Singletonów
  • IOptionsMonitor<T>: bezpieczny dla Singletonów, zapewnia bieżącą wartość przez CurrentValue i powiadomienia przez OnChange
  • Waliduj za pomocą DataAnnotations + ValidateDataAnnotations() + ValidateOnStart()
  • Opcje nazwane służą do obsługi wielu instancji tego samego typu
Bezpłatny start

Ucz się C# dzięki korepetycjom AI — za darmo

Pisz i uruchamiaj kod w przeglądarce, otrzymuj natychmiastową pomoc od korepetytora AI dostępnego 24/7 i kontynuuj naukę w sieci lub w aplikacji.

Kursy
93
Lekcje
346

Często zadawane pytania

Czy lekcja „Silnie typowane opcje z IOptions” jest bezpłatna?

Tak — pełny tekst „Silnie typowane opcje z IOptions” jest dostępny za darmo tutaj w sieci. Aby ćwiczyć ją interaktywnie (wbudowany edytor kodu i tutor AI dostępny 24/7) i odblokować resztę kursu C# Academy, przejdź na CoddyKit PRO. Kurs C# Academy zawiera 4 lekcji w sumie.

Co nauczysz się w „Silnie typowane opcje z IOptions”?

Powiąż sekcje konfiguracji z klasami POCO za pomocą IOptions , IOptionsSnapshot i IOptionsMonitor . Ćwiczysz C# Academy z praktycznym kodem, który uruchamiasz bezpośrednio w przeglądarce, a tutor AI dostępny 24/7 odpowiada na Twoje pytania podczas pracy nad lekcją.

Czy potrzebuję doświadczenia, aby zacząć C# Academy?

Nie wymagamy żadnego doświadczenia. C# Academy w CoddyKit jest strukturyzowany dla początkujących i zaawansowanych użytkowników, więc możesz zacząć tutaj lub od początku i uczyć się w swoim tempie. To lekcja 2 z 4.

Ile czasu zajmuje lekcja „Silnie typowane opcje z IOptions”?

Większość lekcji CoddyKit trwa około 5–10 minut. Każda lekcja to mały, interaktywny krok, dzięki czemu robisz systematyczne postępy i zawsze wracasz dokładnie do tego samego miejsca — na webie i w aplikacji.

Czy mogę pisać i uruchamiać kod w tej lekcji C# Academy?

Tak. Każda lekcja C# Academy zawiera wbudowany edytor kodu, więc piszesz i uruchamiasz prawdziwy kod bezpośrednio w przeglądarce i od razu otrzymujesz sprzężenie zwrotne od AI — bez konfiguracji na komputerze.

Wszystkie lekcje w tym kursie

  1. Źródła i dostawcy konfiguracji
  2. Silnie typowane opcje z IOptions
  3. Walidacja opcji i opcje nazwane
  4. Zarządzanie sekretami
← Powrót do C# Academy