0Pricing
C# Academy · Aula

Ciclos de vida dos serviços: Transient, Scoped e Singleton

Aprenda como os ciclos de vida Transient, Scoped e Singleton afetam a criação, o compartilhamento e a liberação de objetos.

Ciclos de vida dos serviços: Transient, Scoped e Singleton é 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 os ciclos de vida são importantes

O ciclo de vida do serviço controla por quanto tempo uma instância existe e quantas instâncias são criadas. Escolher o ciclo de vida errado causa bugs sutis, como vazamentos de dados entre solicitações ou criação excessiva de objetos.

Transitório: novo a cada vez

Os serviços transitórios são criados do zero sempre que são solicitados ao contêiner. Use-os para serviços leves e sem estado, nos quais compartilhar estado seria perigoso.

builder.Services.AddTransient<IEmailSender, SmtpEmailSender>();

// Each resolution creates a new instance:
// var a = sp.GetRequiredService<IEmailSender>(); // new
// var b = sp.GetRequiredService<IEmailSender>(); // new (different)

Com escopo: uma vez por solicitação

Os serviços com escopo são criados uma vez por scope — normalmente uma solicitação HTTP no ASP.NET Core. A mesma instância é compartilhada durante uma solicitação, mas uma nova é criada para a próxima.

builder.Services.AddScoped<AppDbContext>();

// Within a single HTTP request:
// Both resolve to the SAME AppDbContext instance
// -> consistent unit of work across the request

Instância única: uma durante todo o ciclo de vida do aplicativo

Os serviços de instância única são criados uma vez e reutilizados durante todo o ciclo de vida do aplicativo. Use-os para serviços caros de criar e seguros para uso concorrente, como caches de configuração.

builder.Services.AddSingleton<IMemoryCache, MemoryCache>();

// Or register a pre-built instance:
var config = new AppConfig { MaxRetries = 3 };
builder.Services.AddSingleton<IAppConfig>(config);

Comparando os três

Uma comparação rápida lado a lado:

  • Transitório — nova instância a cada solicitação; utilitários sem estado
  • Com escopo — uma por solicitação HTTP; DbContext, unidade de trabalho
  • De instância única — uma durante todo o ciclo de vida do aplicativo; caches, configurações

O problema da dependência cativa

Injetar um serviço com escopo ou transitório em um serviço de instância única é um erro comum. O serviço de instância única mantém uma referência ao serviço de vida curta, mantendo-o ativo por tempo demais.

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

Detectando violações de escopo

Habilite ValidateScopes para que o contêiner lance uma exceção na inicialização se uma dependência cativa for detectada. Isso identifica erros antes que causem problemas de dados em produção.

builder.Host.UseDefaultServiceProvider(options =>
{
    options.ValidateScopes = true;   // detect captive deps
    options.ValidateOnBuild = true;  // fail fast at start
});

Serviços com escopo fora de uma solicitação

Para resolver serviços com escopo em uma tarefa em segundo plano, crie um escopo explícito usando IServiceScopeFactory. Nunca resolva serviços com escopo diretamente do contêiner raiz.

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

Serviços descartáveis transitórios

Os serviços IDisposable transitórios resolvidos pelo contêiner raiz são rastreados até que o contêiner seja descartado (encerramento do aplicativo). Resolva-os dentro de um escopo para liberar os recursos prontamente.

// Correctly scoped transient disposable
using var scope = sp.CreateScope();
var svc = scope.ServiceProvider.GetRequiredService<MyDisposableService>();
await svc.DoWorkAsync();
// svc.Dispose() called when scope is disposed

Escolhendo o ciclo de vida correto

Um guia simples para decidir:

  • O serviço não tem estado? → Transitório
  • Ele depende de uma solicitação (por exemplo, da identidade do usuário ou de DbContext)? → Com escopo
  • Ele é seguro para uso concorrente e caro de criar? → De instância única

Na prática: os três ciclos de vida juntos

Uma API web típica registra serviços diferentes com ciclos de vida adequados para garantir correção e desempenho.

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ção rápida

Que problema ocorre quando um serviço de instância única mantém uma referência a um serviço com escopo?

Recapitulação: ciclos de vida dos serviços

Principais conclusões:

  • Transitório: nova instância a cada vez — adequado para serviços sem estado e leves
  • Com escopo: uma instância por solicitação — DbContext, repositórios, unidade de trabalho
  • De instância única: uma instância durante todo o ciclo de vida — caches, configurações, utilitários seguros para uso concorrente
  • Nunca injete serviços de vida curta em serviços de vida mais longa (dependência cativa)
  • Use IServiceScopeFactory para resolver serviços com escopo em tarefas em segundo plano

Perguntas Frequentes

A aula “Ciclos de vida dos serviços: Transient, Scoped e Singleton” é grátis?

Sim — o texto completo de “Ciclos de vida dos serviços: Transient, Scoped e Singleton” é 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 “Ciclos de vida dos serviços: Transient, Scoped e Singleton”?

Aprenda como os ciclos de vida Transient, Scoped e Singleton afetam a criação, o compartilhamento e a liberação de objetos. 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 “Ciclos de vida dos serviços: Transient, Scoped e Singleton”?

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

  1. Fundamentos do contêiner de DI
  2. Ciclos de vida dos serviços: Transient, Scoped e Singleton
  3. Injeção pelo construtor e interfaces
  4. Padrões Factory e Options
← Voltar para C# Academy