Durata dei servizi: Transient, Scoped, Singleton
Impari come le durate Transient, Scoped e Singleton influenzano la creazione, la condivisione e lo smaltimento degli oggetti.
Durata dei servizi: Transient, Scoped, Singleton è 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é le durate sono importanti
La durata di un servizio controlla quanto a lungo vive un'istanza e quante istanze vengono create. Scegliere la durata sbagliata causa bug difficili da individuare, come fughe di dati tra richieste o la creazione eccessiva di oggetti.
Transient: una nuova istanza ogni volta
I servizi Transient vengono creati da zero ogni volta che vengono richiesti al container. Li utilizzi per servizi leggeri e senza stato, nei quali condividere lo stato potrebbe essere rischioso.
builder.Services.AddTransient<IEmailSender, SmtpEmailSender>();
// Each resolution creates a new instance:
// var a = sp.GetRequiredService<IEmailSender>(); // new
// var b = sp.GetRequiredService<IEmailSender>(); // new (different)Scoped: una volta per richiesta
I servizi Scoped vengono creati una volta per ogni scope, in genere una richiesta HTTP in ASP.NET Core. La stessa istanza viene condivisa all'interno di una richiesta, mentre per la richiesta successiva ne viene creata una nuova.
builder.Services.AddScoped<AppDbContext>();
// Within a single HTTP request:
// Both resolve to the SAME AppDbContext instance
// -> consistent unit of work across the requestSingleton: uno per tutta la durata dell'applicazione
I servizi Singleton vengono creati una sola volta e riutilizzati per tutta la durata dell'applicazione. Li utilizzi per servizi costosi da creare e sicuri in presenza di più thread, come le cache di configurazione.
builder.Services.AddSingleton<IMemoryCache, MemoryCache>();
// Or register a pre-built instance:
var config = new AppConfig { MaxRetries = 3 };
builder.Services.AddSingleton<IAppConfig>(config);Confronto tra tutte e tre le durate
Un rapido confronto fianco a fianco:
- Transient — nuova istanza a ogni richiesta; utility senza stato
- Scoped — una per richiesta HTTP; DbContext, Unit of Work
- Singleton — una per tutta la durata dell'applicazione; cache, configurazioni
Il problema delle dipendenze captive
Inserire un servizio Scoped o Transient in un Singleton è un errore comune. Il Singleton conserva un riferimento al servizio di breve durata, mantenendolo in vita troppo a lungo.
// BAD: Singleton captures a Scoped service
public class MySingleton
{
private readonly AppDbContext _db; // Scoped!
public MySingleton(AppDbContext db) => _db = db;
// _db is now stuck alive for the app's lifetime
}Rilevamento delle violazioni di scope
Abiliti ValidateScopes affinché il container generi un'eccezione all'avvio se rileva una dipendenza captive. In questo modo gli errori vengono individuati prima che causino problemi ai dati in produzione.
builder.Host.UseDefaultServiceProvider(options =>
{
options.ValidateScopes = true; // detect captive deps
options.ValidateOnBuild = true; // fail fast at start
});Servizi Scoped al di fuori di una richiesta
Per risolvere servizi Scoped in un'attività in background, crei uno scope esplicito utilizzando IServiceScopeFactory. Non risolva mai direttamente i servizi Scoped dal container radice.
public class MyWorker : BackgroundService
{
private readonly IServiceScopeFactory _factory;
public MyWorker(IServiceScopeFactory factory) => _factory = factory;
protected override async Task ExecuteAsync(CancellationToken ct)
{
using var scope = _factory.CreateScope();
var db = scope.ServiceProvider.GetRequiredService<AppDbContext>();
await db.Users.ToListAsync(ct);
}
}Servizi Transient disposable
I servizi IDisposable Transient risolti dal container radice vengono tenuti sotto controllo fino alla sua eliminazione, che avviene allo spegnimento dell'applicazione. Li risolva all'interno di uno scope per rilasciare tempestivamente le risorse.
// Correctly scoped transient disposable
using var scope = sp.CreateScope();
var svc = scope.ServiceProvider.GetRequiredService<MyDisposableService>();
await svc.DoWorkAsync();
// svc.Dispose() called when scope is disposedScelta della durata corretta
Una semplice guida decisionale:
- Il servizio è senza stato? → Transient
- Dipende da una richiesta, ad esempio dall'identità dell'utente o da DbContext? → Scoped
- È sicuro in presenza di più thread e costoso da creare? → Singleton
Caso reale: tre durate insieme
Una tipica web API registra servizi diversi con durate appropriate per garantire correttezza e prestazioni.
builder.Services.AddSingleton<IConfiguration>(builder.Configuration);
builder.Services.AddSingleton<ICacheService, RedisCacheService>();
builder.Services.AddScoped<AppDbContext>();
builder.Services.AddScoped<IOrderRepository, OrderRepository>();
builder.Services.AddScoped<OrderService>();
builder.Services.AddTransient<IEmailSender, SendGridEmailSender>();Verifica rapida
Quale problema si verifica quando un servizio Singleton conserva un riferimento a un servizio Scoped?
Riepilogo: durate dei servizi
Punti chiave:
- Transient: nuova istanza ogni volta; ideale per servizi senza stato e leggeri
- Scoped: una istanza per richiesta; DbContext, repository, unit of work
- Singleton: una istanza per sempre; cache, configurazioni, utility sicure in presenza di più thread
- Non inserisca mai servizi di breve durata in servizi con durata maggiore, per evitare dipendenze captive
- Utilizzi
IServiceScopeFactoryper risolvere servizi Scoped nelle attività in background
Domande Frequenti
La lezione «Durata dei servizi: Transient, Scoped, Singleton» è gratuita?
Sì — il testo completo di «Durata dei servizi: Transient, Scoped, Singleton» è 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 «Durata dei servizi: Transient, Scoped, Singleton»?
Impari come le durate Transient, Scoped e Singleton influenzano la creazione, la condivisione e lo smaltimento degli oggetti. 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 «Durata dei servizi: Transient, Scoped, Singleton»?
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