C# Academy · Lektion

Stærkt typede Options med IOptions

Bind konfigurationssektioner til POCO-klasser med IOptions , IOptionsSnapshot og IOptionsMonitor .

Lektion 2 af 412 trin

Stærkt typede Options med IOptions er en gratis C# Academy-lektion på CoddyKit. Dette er lektion 2 af 4. Du kan læse hele lektionen gratis nedenfor — og derefter øve dig praktisk i browseren med en indbygget kodeeditor og en AI-vejleder, der er tilgængelig døgnet rundt. Den er en del af læringsforløbet i C# Academy, og dine fremskridt synkroniseres på tværs af nettet og CoddyKit-appen. C# Academy-kurset indeholder 4 lektioner i alt.

Hvorfor stærkt typede options?

Læsning af konfiguration med IConfiguration["Key"] giver utypede strenge. Options-mønsteret knytter konfigurationssektioner til C#-klasser og giver typesikkerhed ved kompilering, IntelliSense og understøttelse af validering.

Definition af en options-klasse

Opret en almindelig POCO-klasse, hvis egenskabsnavne svarer til dine JSON-nøgler. Det er konventionen at tilføje en statisk SectionName-konstant, som identificerer konfigurationssektionen.

// 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
  }
}

Registrering af options

Kald Configure<T> for at knytte en konfigurationssektion til options-klassen. Det registrerer IOptions<T>, IOptionsSnapshot<T> og IOptionsMonitor<T> i 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 vs IOptionsSnapshot vs IOptionsMonitor

Der findes tre varianter med forskellige levetider og forskellig genindlæsningsadfærd. Vælg den rigtige til dit anvendelsestilfælde.

// 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);
}

Options-validering med attributter

Forsyn optionsegenskaber med attributter fra System.ComponentModel.DataAnnotations, og kald ValidateDataAnnotations() for at få en fejl med det samme ved opstart, hvis konfigurationen er ugyldig.

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

Brugerdefineret validering med IValidateOptions

Ved komplekse regler på tværs af egenskaber skal du implementere IValidateOptions<T> for at få fuld programmatisk valideringslogik.

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 kører efter alle kald til Configure og lader dig tilsidesætte eller udlede værdier — nyttigt til beregnede egenskaber eller miljøspecifikke justeringer.

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

Navngivne options

Når du har brug for flere instanser af samme optionstype (f.eks. to SMTP-servere), skal du bruge navngivne options til at skelne mellem dem.

// 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");
    }
}

Genvej til BindConfiguration

Kæden AddOptions().BindConfiguration() er den moderne måde at registrere, binde, validere og få fejl med det samme på i ét udtryk.

// 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();

Virkeligt eksempel: Options til funktionsflag

En komplet opsætning af options til funktionsflag med understøttelse af genindlæsning, så funktionsskift kan ændres i appsettings uden genudrulning.

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");
}

Hurtigt tjek

Hvilken IOptions-variant skal du bruge i en singleton-tjeneste, der skal afspejle løbende konfigurationsændringer?

Opsummering: Stærkt typede options med IOptions

Vigtigste pointer:

  • Options-mønsteret binder konfigurationssektioner til POCO'er via Configure<T> eller AddOptions<T>().BindConfiguration()
  • IOptions<T>: Singleton, læser én gang ved opstart
  • IOptionsSnapshot<T>: Scoped, genindlæser pr. anmodning — må ikke injiceres i singleton-tjenester
  • IOptionsMonitor<T>: Sikkert at bruge i singleton-tjenester, med løbende CurrentValue + OnChange
  • Valider med DataAnnotations + ValidateDataAnnotations() + ValidateOnStart()
  • Navngivne options til flere instanser af samme type
Gratis at komme i gang

Lær C# med en AI-underviser — gratis

Skriv og kør rigtig kode i din browser, få øjeblikkelig hjælp fra en AI-underviser døgnet rundt, og fortsæt, hvor du slap, på web eller i appen.

Kurser
93
Lektioner
346

Ofte stillede spørgsmål

Er lektionen “Stærkt typede Options med IOptions” gratis?

Ja — hele teksten til “Stærkt typede Options med IOptions” kan læses gratis her på nettet. Hvis du vil øve dig interaktivt med en indbygget kodeeditor og en AI-vejleder døgnet rundt og få adgang til resten af C# Academy-kurset, skal du opgradere til CoddyKit PRO. C# Academy-kurset indeholder 4 lektioner i alt.

Hvad lærer jeg i “Stærkt typede Options med IOptions”?

Bind konfigurationssektioner til POCO-klasser med IOptions , IOptionsSnapshot og IOptionsMonitor . Du øver dig i C# Academy med praktisk kode, som du kører direkte i browseren, og en AI-vejleder døgnet rundt besvarer dine spørgsmål, mens du arbejder dig gennem lektionen.

Skal jeg have erfaring for at begynde på C# Academy?

Der kræves ingen tidligere erfaring. C# Academy på CoddyKit er tilrettelagt for både begyndere og øvede, så du kan starte her eller fra begyndelsen og lære i dit eget tempo. Dette er lektion 2 af 4.

Hvor lang tid tager lektionen “Stærkt typede Options med IOptions”?

De fleste CoddyKit-lektioner tager cirka 5–10 minutter. Hver lektion er kort og interaktiv, så du gør løbende fremskridt og kan fortsætte, hvor du slap – på både web og app.

Kan jeg skrive og køre kode i denne C# Academy-lektion?

Ja. Alle C# Academy-lektioner har en indbygget kodeeditor, så du kan skrive og køre rigtig kode direkte i din browser og få øjeblikkelig feedback fra AI – uden lokal opsætning.

Alle lektioner i dette kursus

  1. Konfigurationskilder og -udbydere
  2. Stærkt typede Options med IOptions
  3. Validering af Options og navngivne Options
  4. Håndtering af secrets
← Tilbage til C# Academy