Pattern Factory e Options
Usi factory delegate, IServiceProvider e il pattern Options per gestire dipendenze condizionali o configurabili.
Pattern Factory e Options è una lezione C# Academy gratuita su CoddyKit. Questa è la lezione 4 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.
Quando l'iniezione tramite costruttore non basta
A volte è necessario creare servizi in modo condizionale, in base a dati disponibili durante l'esecuzione, oppure configurarli in modo diverso per ogni caso d'uso. È in questi casi che i pattern Factory e Options sono particolarmente utili.
Factory delegate con AddTransient
Può passare una factory delegate a AddTransient, AddScoped o AddSingleton. La delegate riceve IServiceProvider, consentendo di risolvere altri servizi.
builder.Services.AddTransient<IPaymentGateway>(sp =>
{
var config = sp.GetRequiredService<IOptions<PaymentConfig>>().Value;
return config.Provider == "stripe"
? new StripeGateway(config.ApiKey)
: new PayPalGateway(config.ClientId, config.Secret);
});Options denominate con IOptionsSnapshot
Il pattern Options associa le sezioni di configurazione a classi fortemente tipizzate. Utilizzi IOptions<T> per i Singleton e IOptionsSnapshot<T> per i valori aggiornati a ogni richiesta.
public class SmtpSettings
{
public string Host { get; set; } = "";
public int Port { get; set; } = 587;
public string Username { get; set; } = "";
}
// Registration
builder.Services.Configure<SmtpSettings>(
builder.Configuration.GetSection("Smtp"));
// Consumption
public class EmailService
{
private readonly SmtpSettings _settings;
public EmailService(IOptions<SmtpSettings> opts)
=> _settings = opts.Value;
}IOptionsMonitor per l'hot reload
IOptionsMonitor<T> fornisce il valore corrente dell'opzione al momento dell'accesso e invia una notifica quando la configurazione cambia: è perfetto per i Singleton che devono ricevere aggiornamenti della configurazione in tempo reale.
public class FeatureFlagService
{
private readonly IOptionsMonitor<FeatureFlags> _monitor;
public FeatureFlagService(IOptionsMonitor<FeatureFlags> monitor)
=> _monitor = monitor;
public bool IsEnabled(string flag)
{
// Always reads the latest config value
return _monitor.CurrentValue.Flags.GetValueOrDefault(flag);
}
}Options denominate
Le options denominate consentono di registrare più configurazioni dello stesso tipo. Utilizzi Configure<T>(name, ...) e risolva il valore con IOptionsSnapshot<T>.Get(name).
builder.Services.Configure<S3Settings>("primary",
builder.Configuration.GetSection("S3:Primary"));
builder.Services.Configure<S3Settings>("backup",
builder.Configuration.GetSection("S3:Backup"));
public class S3Service
{
public S3Service(IOptionsSnapshot<S3Settings> opts)
{
var primary = opts.Get("primary");
var backup = opts.Get("backup");
}
}Convalida delle Options all'avvio
Utilizzi ValidateDataAnnotations() o un validator personalizzato per verificare che la configurazione sia corretta prima dell'avvio dell'applicazione. Lo combini con ValidateOnStart() per ottenere un comportamento fail-fast.
public class SmtpSettings
{
[Required] public string Host { get; set; } = "";
[Range(1, 65535)] public int Port { get; set; } = 587;
}
builder.Services
.AddOptions<SmtpSettings>()
.Bind(builder.Configuration.GetSection("Smtp"))
.ValidateDataAnnotations()
.ValidateOnStart();Pattern Abstract Factory
Un'interfaccia Abstract Factory consente di inserire una factory nei servizi, rimandando la costruzione fino a quando non sono disponibili i dati di runtime, senza creare una dipendenza diretta da IServiceProvider.
public interface IReportFactory
{
IReport Create(string reportType);
}
public class ReportFactory : IReportFactory
{
private readonly IServiceProvider _sp;
public ReportFactory(IServiceProvider sp) => _sp = sp;
public IReport Create(string reportType) => reportType switch
{
"pdf" => _sp.GetRequiredService<PdfReport>(),
"excel"=> _sp.GetRequiredService<ExcelReport>(),
_ => throw new ArgumentException("Unknown type")
};
}
builder.Services.AddTransient<IReportFactory, ReportFactory>();Servizi keyed (.NET 8)
.NET 8 introduce i servizi keyed: registri più implementazioni con chiavi diverse e risolva quella corretta con [FromKeyedServices] o GetKeyedService.
builder.Services.AddKeyedScoped<IPaymentGateway, StripeGateway>("stripe");
builder.Services.AddKeyedScoped<IPaymentGateway, PayPalGateway>("paypal");
// Resolve in a class:
public class CheckoutService(
[FromKeyedServices("stripe")] IPaymentGateway stripe,
[FromKeyedServices("paypal")] IPaymentGateway paypal) { }PostConfigure per le sostituzioni
PostConfigure viene eseguito dopo tutte le chiamate a Configure. Lo utilizzi per applicare sostituzioni nei test o per imporre invarianti indipendentemente dalla configurazione caricata.
// In integration tests: force test values after real config
builder.Services.PostConfigure<SmtpSettings>(opts =>
{
opts.Host = "smtp.test.local";
opts.Port = 25;
});Metodi di estensione di IServiceCollection
Raccolga le registrazioni in metodi di estensione per mantenere pulito Program.cs e rendere i moduli riutilizzabili in più progetti.
public static class ServiceCollectionExtensions
{
public static IServiceCollection AddPaymentServices(
this IServiceCollection services,
IConfiguration config)
{
services.Configure<PaymentConfig>(config.GetSection("Payment"));
services.AddScoped<IPaymentGateway, StripeGateway>();
services.AddScoped<PaymentService>();
return services;
}
}
// Usage in Program.cs:
builder.Services.AddPaymentServices(builder.Configuration);Caso reale: notifiche con più provider
Utilizzando insieme una factory e le options denominate, può selezionare a runtime il provider di notifiche corretto in base alla preferenza dell'utente memorizzata nel database.
builder.Services.AddKeyedScoped<INotifier, EmailNotifier>("email");
builder.Services.AddKeyedScoped<INotifier, SmsNotifier>("sms");
builder.Services.AddKeyedScoped<INotifier, PushNotifier>("push");
public class NotificationService
{
private readonly IServiceProvider _sp;
public NotificationService(IServiceProvider sp) => _sp = sp;
public Task SendAsync(string channel, string message)
{
var notifier = _sp.GetRequiredKeyedService<INotifier>(channel);
return notifier.SendAsync(message);
}
}Verifica rapida
Quale interfaccia fornisce il valore corrente delle options E invia notifiche quando la configurazione cambia, risultando quindi adatta ai servizi Singleton?
Riepilogo: pattern Factory e Options
Punti chiave:
- Le factory delegate nei metodi
Add*consentono di creare servizi in modo condizionale o configurato a runtime - Il pattern Options associa le sezioni di configurazione a POCO fortemente tipizzati
IOptions= statiche,IOptionsSnapshot= per richiesta,IOptionsMonitor= aggiornamenti in tempo reale- Convalidi le options all'avvio con
ValidateDataAnnotations().ValidateOnStart() - I servizi keyed (.NET 8) sostituiscono le soluzioni basate su factory per le implementazioni denominate
Domande Frequenti
La lezione «Pattern Factory e Options» è gratuita?
Sì — il testo completo di «Pattern Factory e Options» è 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 «Pattern Factory e Options»?
Usi factory delegate, IServiceProvider e il pattern Options per gestire dipendenze condizionali o configurabili. 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 4 di 4.
Quanto tempo richiede la lezione «Pattern Factory e Options»?
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
- Fondamenti dei container DI
- Durata dei servizi: Transient, Scoped, Singleton
- Iniezione tramite costruttore e interfacce
- Pattern Factory e Options