Dependency Injection para Iniciantes
Quando comecei a aprender .NET, um conceito que me confundiu bastante foi Dependency Injection. Principalmente por causa da forma como era explicado muitas vezes com muita linguagem técnica e complicada.
Então neste artigo eu vou explicar isso em termos muito simples.
O que é Dependency Injection?
Dependency Injection é uma técnica onde uma classe não cria suas próprias dependências.
Em vez disso, as dependências são fornecidas para a classe através do construtor.
Isso reduz o acoplamento forte (tight coupling) e torna a aplicação mais fácil de manter e testar.
Exemplo
Sem Dependency Injection:
public class UserService
{
private UserRepository _userRepository = new UserRepository();
}
O serviço cria sua própria dependência, o que o torna fortemente acoplado.
Com Dependency Injection:
public class UserService
{
private readonly UserRepository _userRepository;
public UserService(UserRepository userRepository)
{
_userRepository = userRepository;
}
}
Agora a dependência é injetada através do construtor.
Mas de onde vem o UserRepository?
Registrando Serviços
No ASP.NET Core registramos serviços no arquivo Program.cs.
builder.Services.AddScoped<UserRepository>();
O ASP.NET Core possui um container IoC (Inversion of Control) embutido que gerencia essas dependências.
Quando a aplicação precisa de UserRepository, o container automaticamente fornece essa instância.
Ciclo de Vida dos Serviços
O ASP.NET Core suporta três tipos de ciclo de vida para serviços.
Scoped
Um serviço Scoped é criado uma vez por requisição HTTP.
Isso é muito comum para coisas como contextos de banco de dados.
Singleton
Um serviço Singleton é criado uma única vez durante toda a execução da aplicação.
Todas as requisições usam a mesma instância.
Transient
Um serviço Transient cria uma nova instância toda vez que ele é solicitado.
Isso é útil para serviços leves que não precisam manter estado.
Dependency Inversion
Ao aprender Dependency Injection, você também ouvirá falar sobre o Princípio da Inversão de Dependência, que faz parte dos princípios SOLID.
Ele diz o seguinte:
Módulos de alto nível não devem depender de módulos de baixo nível. Ambos devem depender de abstrações.
Na prática, isso geralmente significa usar interfaces.
Exemplo:
public interface IUserRepository
{
User GetById(int id);
}
Implementação:
public class UserRepository : IUserRepository
{
public User GetById(int id)
{
// lógica de banco de dados
}
}
Registro do serviço:
builder.Services.AddScoped<IUserRepository, UserRepository>();
Agora suas classes dependem de interfaces em vez de implementações concretas.
Considerações Finais
Dependency Injection pode parecer complicado no começo, mas a ideia principal é simples:
- Não crie dependências dentro das suas classes
- Receba essas dependências de fora
- Deixe o framework gerenciar o ciclo de vida delas
Depois que você entende isso, muitas partes da arquitetura do ASP.NET Core começam a fazer muito mais sentido.