0Pricing
C# Academy · Lezione

Opzioni fortemente tipizzate con IOptions

Colleghi le sezioni di configurazione a classi POCO usando IOptions , IOptionsSnapshot e IOptionsMonitor .

Opzioni fortemente tipizzate con IOptions è una lezione C# Academy gratuita su CoddyKit. Questa è la lezione 2 di 4. Puoi leggere la lezione completa qui gratuitamente — poi esercitati direttamente nel browser con un editor di codice integrato e un tutor IA disponibile 24/7. Fa parte del percorso di apprendimento C# Academy, e i tuoi progressi si sincronizzano tra il web e l'app CoddyKit. Il corso C# Academy include 4 lezioni in totale.

Perché utilizzare opzioni fortemente tipizzate?

La lettura della configurazione con IConfiguration["Key"] restituisce stringhe prive di tipo. Il pattern delle opzioni associa le sezioni di configurazione a classi C#, offrendo sicurezza in fase di compilazione, IntelliSense e supporto per la convalida.

Definizione di una classe Options

Crei una semplice classe POCO i cui nomi delle proprietà corrispondano alle chiavi JSON. Per convenzione, aggiunga una costante statica SectionName per identificare la sezione di configurazione.

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

Registrazione delle opzioni

Chiami Configure<T> per associare una sezione di configurazione alla classe delle opzioni. In questo modo registra IOptions<T>, IOptionsSnapshot<T> e IOptionsMonitor<T> nella 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, IOptionsSnapshot e IOptionsMonitor a confronto

Esistono tre varianti, con durate e comportamenti di ricaricamento diversi. Scelga quella più adatta al proprio caso d'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);
}

Convalida delle opzioni con gli attributi

Decori le proprietà delle opzioni con gli attributi di System.ComponentModel.DataAnnotations e chiami ValidateDataAnnotations() per interrompere subito l'avvio se la configurazione non è valida.

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

Convalida personalizzata con IValidateOptions

Per regole complesse tra più proprietà, implementi IValidateOptions<T> per ottenere una logica di convalida programmatica 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>();

Post-configurazione

PostConfigure viene eseguito dopo tutte le chiamate a Configure e consente di sovrascrivere o derivare valori, risultando utile per proprietà calcolate o adattamenti specifici dell'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 validators

Opzioni denominate

Quando sono necessarie più istanze dello stesso tipo di opzioni, ad esempio due server SMTP, utilizzi le opzioni denominate per distinguerle.

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

Forma abbreviata di BindConfiguration

La catena AddOptions().BindConfiguration() è il moderno approccio fluente per registrare, associare, convalidare e interrompere subito l'esecuzione, tutto in un'unica espressione.

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

Caso reale: opzioni per i flag delle funzionalità

Una configurazione completa delle opzioni per i flag delle funzionalità, con supporto per il ricaricamento, che consente di modificare gli interruttori in appsettings senza ridistribuire l'applicazione.

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 rapida

Quale variante di IOptions dovrebbe utilizzare in un servizio Singleton che deve riflettere le modifiche alla configurazione in tempo reale?

Riepilogo: opzioni fortemente tipizzate con IOptions

Concetti chiave:

  • Il pattern delle opzioni associa le sezioni di configurazione a oggetti POCO tramite Configure<T> o AddOptions<T>().BindConfiguration()
  • IOptions<T>: Singleton, legge i valori una volta all'avvio
  • IOptionsSnapshot<T>: Scoped, ricarica i valori a ogni richiesta — non lo inietti nei Singleton
  • IOptionsMonitor<T>: sicuro nei Singleton, con CurrentValue aggiornato in tempo reale e OnChange
  • Convalidi con DataAnnotations + ValidateDataAnnotations() + ValidateOnStart()
  • Utilizzi le opzioni denominate per più istanze dello stesso tipo

Domande Frequenti

La lezione «Opzioni fortemente tipizzate con IOptions» è gratuita?

Sì — il testo completo di «Opzioni fortemente tipizzate con IOptions» è gratuito qui sul web. Per esercitarvi in modo interattivo (un editor di codice integrato e un tutor IA 24/7) e sbloccare il resto del corso C# Academy, passa a CoddyKit PRO. Il corso C# Academy include 4 lezioni in totale.

Cosa imparerò in «Opzioni fortemente tipizzate con IOptions»?

Colleghi le sezioni di configurazione a classi POCO usando IOptions , IOptionsSnapshot e IOptionsMonitor . Eserciti C# Academy con codice pratico che esegui direttamente nel browser, e un tutor IA 24/7 risponde alle tue domande mentre lavori sulla lezione.

Ho bisogno di esperienza per iniziare C# Academy?

Non è richiesta alcuna esperienza precedente. C# Academy su CoddyKit è strutturato per principianti e studenti avanzati, quindi puoi iniziare da qui o dall'inizio e procedere al tuo ritmo. Questa è la lezione 2 di 4.

Quanto tempo richiede la lezione «Opzioni fortemente tipizzate con IOptions»?

La maggior parte delle lezioni CoddyKit richiede circa 5–10 minuti. Ogni lezione è breve e interattiva, quindi fai progressi costanti e riprendi esattamente da dove hai lasciato su web e app.

Posso scrivere ed eseguire codice in questa lezione C# Academy?

Sì. Ogni lezione C# Academy include un editor di codice integrato, quindi scrivi ed esegui codice reale direttamente nel tuo browser e ricevi feedback istantaneo dall'IA — nessuna configurazione locale necessaria.

Tutte le lezioni di questo corso

  1. Fonti e provider di configurazione
  2. Opzioni fortemente tipizzate con IOptions
  3. Convalida delle opzioni e opzioni denominate
  4. Gestione dei segreti
← Torna a C# Academy