Dependency Injection
Constructor Injection, Lifetimes, Composition Root e testabilidade em .NET
DI fornece dependencias de fora (via construtor) em vez de cria-las internamente. Isso desacopla o codigo, melhora a testabilidade e torna os lifetimes explicitos.
O que e Dependency Injection?
DI e um padrao onde uma classe recebe suas dependencias em vez de criar internamente. O mecanismo mais comum e Constructor Injection: a dependencia e passada como parametro do construtor.
public interface IClock { DateTime UtcNow { get; } }
public sealed class SystemClock : IClock { public DateTime UtcNow => DateTime.UtcNow; }
public sealed class Greeter
{
private readonly IClock _clock;
public Greeter(IClock clock) => _clock = clock;
public string Greet(string name) => $"[{_clock.UtcNow:o}] Hello, {name}!";
}
Dependemos da abstracao (IClock), nao do tipo concreto. Greeter e facil de testar (injete um fake clock), e o codigo de producao injeta SystemClock.
Composition Root
O Composition Root e o unico lugar onde todas as dependencias sao registradas e conectadas. Em ASP.NET Core, isso e o Program.cs / Startup.cs. Nenhuma outra classe deve saber que o container existe.
// Program.cs β o Composition Root
var builder = WebApplication.CreateBuilder(args);
// Registre TODAS as dependencias aqui, uma unica vez
builder.Services.AddSingleton<IClock, SystemClock>();
builder.Services.AddTransient<Greeter>();
builder.Services.AddScoped<IOrderRepository, SqlOrderRepository>();
var app = builder.Build();
// Daqui pra frente, nenhuma classe sabe que o container existe
Fluxo de resolucao do container
Principios fundamentais
| Principio | Descricao | Beneficio |
|---|---|---|
| Depend on abstractions | Use interfaces (IClock), nao classes concretas | Permite trocar implementacoes sem mudar consumidores |
| Constructor Injection | Dependencias declaradas como parametros do construtor | Dependencias visiveis, validadas na compilacao |
| Composition Root | Um unico ponto de registro (Program.cs) | Toda a configuracao em um lugar so |
| Explicit dependencies | Nao usar new para dependencias dentro de classes | Testabilidade e clareza |
Como DI se relaciona com o Dependency Inversion Principle (SOLID)?
O Dependency Inversion Principle diz que modulos de alto nivel nao devem depender de modulos de baixo nivel - ambos devem depender de abstracoes. DI e o mecanismo que implementa esse principio: o container injeta a implementacao correta da abstracao no construtor.