Stærkt typede Options med IOptions
Bind konfigurationssektioner til POCO-klasser med IOptions , IOptionsSnapshot og IOptionsMonitor .
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 useBrugerdefineret 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 validatorsNavngivne 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>ellerAddOptions<T>().BindConfiguration() IOptions<T>: Singleton, læser én gang ved opstartIOptionsSnapshot<T>: Scoped, genindlæser pr. anmodning — må ikke injiceres i singleton-tjenesterIOptionsMonitor<T>: Sikkert at bruge i singleton-tjenester, med løbendeCurrentValue+OnChange- Valider med DataAnnotations +
ValidateDataAnnotations()+ValidateOnStart() - Navngivne options til flere instanser af samme type
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
- Konfigurationskilder og -udbydere
- Stærkt typede Options med IOptions
- Validering af Options og navngivne Options
- Håndtering af secrets