Options fortemente tipadas com IOptions
Associe seções de configuração a classes POCO usando IOptions , IOptionsSnapshot e IOptionsMonitor .
Options fortemente tipadas com IOptions é uma aula grátis de C# Academy no CoddyKit. Esta é a aula 2 de 4. Você pode ler a aula completa abaixo gratuitamente — depois pratica ao vivo no navegador com um editor de código integrado e um tutor de IA 24/7. Faz parte do caminho de aprendizado de C# Academy, e seu progresso é sincronizado entre a web e o app CoddyKit. O curso de C# Academy inclui 4 aulas no total.
Por que usar opções fortemente tipadas?
Ler a configuração com IConfiguration["Key"] fornece cadeias de caracteres sem tipo. O padrão de opções mapeia seções de configuração para classes C#, oferecendo segurança em tempo de compilação, IntelliSense e suporte à validação.
Definição de uma classe de opções
Crie uma classe POCO simples cujos nomes de propriedades correspondam às suas chaves JSON. Por convenção, adicione uma constante estática SectionName para identificar a seção de configuração.
// 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
}
}Registro de opções
Chame Configure<T> para associar uma seção de configuração à classe de opções. Isso registra IOptions<T>, IOptionsSnapshot<T> e IOptionsMonitor<T> no 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
Há três variantes, com diferentes tempos de vida e comportamentos de recarregamento. Escolha a mais adequada ao seu caso de uso.
// 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);
}Validação de opções com atributos
Adicione atributos System.ComponentModel.DataAnnotations às propriedades das opções e chame ValidateDataAnnotations() para falhar imediatamente na inicialização caso a configuração seja inválida.
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 useValidação personalizada com IValidateOptions
Para regras complexas entre propriedades, implemente IValidateOptions<T> para obter uma lógica de validação programática completa.
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>();Configuração posterior
PostConfigure é executado depois de todas as chamadas a Configure e permite substituir ou derivar valores — útil para propriedades calculadas ou ajustes específicos do ambiente.
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 validatorsOpções nomeadas
Quando você precisa de várias instâncias do mesmo tipo de opções (por exemplo, dois servidores SMTP), use opções nomeadas para diferenciá-las.
// 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");
}
}Atalho BindConfiguration
A cadeia AddOptions().BindConfiguration() é a forma moderna e fluente de registrar, associar, validar e falhar imediatamente, tudo em uma única expressão.
// 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();Exemplo do mundo real: opções de sinalizadores de funcionalidade
Uma configuração completa de opções de sinalizadores de funcionalidade com suporte a recarregamento, permitindo alterar alternâncias no appsettings sem uma nova implantação.
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");
}Verificação rápida
Qual variante de IOptions você deve usar em um serviço de instância única que precisa refletir alterações de configuração em tempo real?
Recapitulação: opções fortemente tipadas com IOptions
Principais conclusões:
- O padrão de opções associa seções de configuração a POCOs por meio de
Configure<T>ouAddOptions<T>().BindConfiguration() IOptions<T>: instância única, lê uma vez na inicializaçãoIOptionsSnapshot<T>: com escopo, recarrega a cada solicitação — não o injete em serviços de instância únicaIOptionsMonitor<T>: seguro para serviços de instância única, comCurrentValue+OnChangeem tempo real- Valide com DataAnnotations +
ValidateDataAnnotations()+ValidateOnStart() - Use opções nomeadas para várias instâncias do mesmo tipo
Aprenda C# com um tutor de IA — grátis
Escreva e execute código real no seu navegador, obtenha ajuda instantânea de um tutor de IA 24/7 e continue de onde parou na web ou no app.
- Cursos
- 93
- Aulas
- 346
Perguntas Frequentes
A aula “Options fortemente tipadas com IOptions” é grátis?
Sim — o texto completo de “Options fortemente tipadas com IOptions” é grátis para ler aqui na web. Para praticá-la interativamente (um editor de código integrado e um tutor de IA 24/7) e desbloquear o restante do curso de C# Academy, atualize para CoddyKit PRO. O curso de C# Academy inclui 4 aulas no total.
O que vou aprender em “Options fortemente tipadas com IOptions”?
Associe seções de configuração a classes POCO usando IOptions , IOptionsSnapshot e IOptionsMonitor . Você pratica C# Academy com código prático que executa diretamente no navegador, e um tutor de IA 24/7 responde suas dúvidas enquanto trabalha na aula.
Preciso ter experiência prévia para começar C# Academy?
Nenhuma experiência prévia é necessária. C# Academy no CoddyKit é estruturado para alunos iniciantes até avançados, então você pode começar aqui ou desde o início e aprender no seu ritmo. Esta é a aula 2 de 4.
Quanto tempo leva a aula “Options fortemente tipadas com IOptions”?
A maioria das aulas CoddyKit leva cerca de 5–10 minutos. Cada uma é compacta e interativa, então você faz progresso constante e retoma exatamente de onde parou entre web e app.
Posso escrever e executar código nesta aula de C# Academy?
Sim. Cada aula de C# Academy inclui um editor de código integrado, então você escreve e executa código real direto no navegador e recebe feedback de IA instantaneamente — nenhuma configuração local necessária.
Todas as aulas deste curso
- Fontes e provedores de configuração
- Options fortemente tipadas com IOptions
- Validação de Options e Options nomeadas
- Gerenciamento de segredos