C# Academy · Aula

Fundamentos do contêiner de DI

Entenda a inversão de controle, o registro de serviços e como o contêiner de DI do .NET resolve dependências.

Aula 1 de 413 etapas

Fundamentos do contêiner de DI é uma aula grátis de C# Academy no CoddyKit. Esta é a aula 1 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.

O que é injeção de dependências?

Injeção de dependências (DI) é um padrão de projeto no qual uma classe recebe suas dependências de uma fonte externa, em vez de criá-las por conta própria.

Em vez de escrever var repo = new UserRepository(); dentro de uma classe, a classe declara do que precisa e o contêiner de DI fornece isso.

Inversão de controle

DI é uma implementação concreta do princípio da inversão de controle (IoC): o controle da criação das dependências é invertido da classe dependente para um contêiner externo.

Isso torna as classes mais fáceis de testar e substituir.

Configurando o contêiner de DI do .NET

Em um aplicativo .NET, o contêiner de DI é configurado por meio de IServiceCollection em Program.cs. Os serviços são registrados e, em seguida, resolvidos pelo tempo de execução.

var builder = WebApplication.CreateBuilder(args);

// Register services
builder.Services.AddScoped<IUserRepository, UserRepository>();
builder.Services.AddScoped<UserService>();

var app = builder.Build();
app.Run();

Definindo uma interface e uma implementação

A DI funciona melhor quando você programa para interfaces. Defina uma interface para o contrato do serviço e uma classe concreta que o implemente.

public interface IUserRepository
{
    User? GetById(int id);
}

public class UserRepository : IUserRepository
{
    public User? GetById(int id)
    {
        // fetch from database
        return new User { Id = id, Name = "Alice" };
    }
}

Resolvendo serviços por meio do construtor

O contêiner injeta automaticamente os serviços registrados nos construtores. A classe só precisa declarar a interface de que precisa — não é necessária a palavra-chave new.

public class UserService
{
    private readonly IUserRepository _repo;

    public UserService(IUserRepository repo)
    {
        _repo = repo;
    }

    public User? FindUser(int id) => _repo.GetById(id);
}

Registrando vários serviços

Você pode registrar quantos serviços forem necessários. Os métodos de extensão mais comuns são AddTransient, AddScoped e AddSingleton — cada um define um ciclo de vida diferente.

builder.Services.AddSingleton<IConfig, AppConfig>();
builder.Services.AddScoped<IUserRepository, UserRepository>();
builder.Services.AddTransient<IEmailService, SmtpEmailService>();
builder.Services.AddScoped<UserService>();

Usando IServiceProvider diretamente

Em casos raros, é necessário resolver serviços de forma imperativa. IServiceProvider permite chamar GetRequiredService<T>() para resolver um serviço, mas prefira a injeção pelo construtor na maioria dos cenários.

// Anti-pattern (service locator) — use sparingly
public class ManualResolver
{
    private readonly IServiceProvider _sp;

    public ManualResolver(IServiceProvider sp) => _sp = sp;

    public void DoWork()
    {
        var svc = _sp.GetRequiredService<UserService>();
        svc.FindUser(1);
    }
}

Registrando genéricos abertos

A DI do .NET oferece suporte a registros de genéricos abertos. Você pode registrar IRepository<> uma vez, e ele será resolvido como Repository<T> para qualquer tipo de entidade.

builder.Services.AddScoped(typeof(IRepository<>), typeof(Repository<>));

// Resolves as:
// IRepository<User> -> Repository<User>
// IRepository<Order> -> Repository<Order>

Validação na inicialização

Com ValidateOnStart() ou ValidateScopes = true, o contêiner pode detectar registros configurados incorretamente (como capturar um serviço com escopo dentro de um serviço de instância única) na inicialização do aplicativo, em vez de fazê-lo em tempo de execução.

builder.Services.AddScoped<IMyService, MyService>();

// Detect scope violations at startup
builder.Host.UseDefaultServiceProvider(options =>
{
    options.ValidateScopes = true;
    options.ValidateOnBuild = true;
});

Decorando serviços

Você pode envolver um serviço com um decorador sem modificar a classe original. Primeiro registre o serviço interno e, depois, registre o decorador que o envolve.

builder.Services.AddScoped<IUserRepository, UserRepository>();

// Decorator pattern
builder.Services.Decorate<IUserRepository, CachedUserRepository>();
// Requires Scrutor NuGet package

Na prática: API mínima com DI

Em uma API mínima, os serviços são injetados diretamente nos parâmetros do manipulador de rotas. O contêiner os resolve automaticamente.

app.MapGet("/users/{id}", (int id, UserService svc) =>
{
    var user = svc.FindUser(id);
    return user is null ? Results.NotFound() : Results.Ok(user);
});

Verificação rápida

Qual método você deve preferir para obter dependências na maioria das classes?

Recapitulação: fundamentos do contêiner de DI

Principais conclusões:

  • A DI inverte a criação de dependências: o contêiner cria os objetos, não a própria classe
  • Registre serviços com AddTransient / AddScoped / AddSingleton
  • A injeção pelo construtor é a abordagem padrão e preferida
  • Genéricos abertos, decoradores e ValidateOnBuild são recursos avançados poderosos
Grátis para começar

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 “Fundamentos do contêiner de DI” é grátis?

Sim — o texto completo de “Fundamentos do contêiner de DI” é 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 “Fundamentos do contêiner de DI”?

Entenda a inversão de controle, o registro de serviços e como o contêiner de DI do .NET resolve dependências. 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 1 de 4.

Quanto tempo leva a aula “Fundamentos do contêiner de DI”?

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