C#: Injeção de dependência no .NET
Rocketseat

Rocketseat

4 min de leitura
CSharp
Você já passou horas tentando descobrir por que uma pequena mudança em uma parte do código quebrou outra parte completamente diferente? Já teve dificuldades em testar uma classe porque ela dependia de muitos outros componentes? Imagine ter que alterar uma funcionalidade em dezenas de lugares diferentes do seu código só porque uma dependência mudou... Esses são problemas comuns causados pelo acoplamento forte no código.
O acoplamento forte ocorre quando uma classe depende intensamente de outra, tornando o sistema rígido e difícil de manter. Isso pode levar a dificuldades na reutilização de classes, necessidade de alterações em cascata e complexidade na compreensão do código.
Felizmente, existe uma técnica que pode resolver esses problemas: a injeção de dependência (DI). Neste artigo, vamos explorar como a DI pode tornar seu código mais limpo, testável e fácil de manter, preparando você para um futuro profissional brilhante.

O que é injeção de dependência e por que ela importa?

Em programação, uma dependência é um objeto que uma classe precisa para funcionar. Por exemplo, uma classe Pedido pode depender de um serviço de notificação para enviar confirmações aos clientes. Quando uma classe cria diretamente suas dependências, ocorre o acoplamento forte, o que dificulta testes e manutenções.
A injeção de dependência é uma técnica que permite fornecer as dependências que uma classe necessita de forma externa, eliminando a necessidade de a própria classe instanciá-las. Isso reduz o acoplamento, tornando o código mais flexível e facilitando a realização de testes unitários.
Analogia: imagine que seu código é um carro e as dependências são as peças. Com a DI, você pode trocar facilmente uma peça (dependência) sem precisar desmontar o carro inteiro, facilitando a manutenção e a evolução do veículo.

Desvendando os conceitos fundamentais

Para compreender plenamente a injeção de dependência, é essencial familiarizar-se com alguns conceitos-chave:
  • Dependência: é um objeto que uma classe precisa para funcionar.
  • Acoplamento: refere-se ao nível de interdependência entre módulos de um sistema. Um acoplamento forte indica que as classes estão fortemente ligadas, dificultando alterações e testes.
  • Inversão de controle (IoC): é um princípio onde o controle do fluxo do programa é invertido, ou seja, em vez de a própria classe gerenciar suas dependências, um contêiner externo faz isso. A DI é uma forma de implementar o IoC.
  • Contêiner de injeção de dependência: é um framework que gerencia a criação e o ciclo de vida das dependências, injetando-as onde são necessárias.

Mãos à obra: injeção de dependência no .NET

O .NET fornece um contêiner de DI nativo que facilita a implementação dessa técnica. Existem três formas principais de realizar a injeção de dependência:

1. Injeção via construtor

É a forma mais comum e recomendada. As dependências são passadas como parâmetros no construtor da classe.
// Interface que define o contrato para o serviço de notificação public interface INotificador { void EnviarMensagem(string mensagem); } // Implementação da interface INotificador public class EmailNotificador : INotificador { public void EnviarMensagem(string mensagem) { // Lógica para enviar e-mail } } // Classe Pedido que depende de um serviço de notificação public class Pedido { private readonly INotificador _notificador; public Pedido(INotificador notificador) { _notificador = notificador; } public void Processar() { _notificador.EnviarMensagem("Pedido processado com sucesso."); } }

2. Injeção de propriedade

As dependências são atribuídas através de propriedades públicas.
// Definição da classe Pedido com injeção por propriedade public class Pedido { public INotificador Notificador { get; set; } public void Processar() { Notificador?.EnviarMensagem("Pedido processado com sucesso."); } } // Exemplo prático de utilização var pedido = new Pedido(); pedido.Notificador = new EmailNotificador(); pedido.Processar();
Ao utilizar interfaces (como INotificador), você garante maior flexibilidade, permitindo trocar facilmente diferentes implementações no futuro, como substituir o envio por e-mail por notificações via SMS, sem precisar alterar toda a lógica da classe.

3. Injeção de método

As dependências são passadas como parâmetros em métodos específicos.
public class Pedido { public void Processar(INotificador notificador) { notificador.EnviarMensagem("Pedido processado com sucesso."); } }

Como escolher a técnica ideal para seu contexto?

Cada técnica de injeção tem cenários nos quais é mais indicada. Veja abaixo como escolher a mais adequada de acordo com suas necessidades:
  • Injeção via construtor:
    • Recomendado para dependências obrigatórias. Garante que todos os objetos necessários sejam fornecidos já na criação da classe, tornando claro quais dependências a classe precisa para funcionar corretamente. É a técnica mais indicada na maioria dos casos.
  • Injeção de propriedade:
    • Indicada especialmente para dependências opcionais. Se sua classe pode funcionar sem uma determinada dependência ou se essa dependência pode mudar dinamicamente em tempo de execução, essa pode ser a melhor opção.
  • Injeção de método:
    • Ideal quando a dependência é utilizada apenas em métodos específicos, geralmente de forma pontual ou temporária. Evita que a dependência fique associada à classe por mais tempo que o necessário.
Exemplo prático de contexto real:
Se você tem uma classe Pedido que sempre precisa enviar notificações ao processar um pedido, a melhor escolha é a injeção via construtor. Já se precisar gerar notificações apenas ocasionalmente ou em situações específicas, use a injeção por método.

Como registrar dependências no contêiner do .NET

Para que o .NET entenda quais implementações fornecer quando sua aplicação solicitar uma dependência, é essencial registrá-las no contêiner de injeção de dependência. Veja como isso pode ser feito de maneira simples:
Exemplo prático:
No arquivo Program.cs (para aplicações .NET modernas, como .NET 6 ou superior), você pode fazer assim:
var builder = WebApplication.CreateBuilder(args); // Registro de dependências builder.Services.AddTransient<INotificador, EmailNotificador>(); var app = builder.Build(); app.Run();
Neste exemplo:
  • AddTransient: Uma nova instância da dependência (EmailNotificador) é criada sempre que solicitada. Indicado para serviços leves e sem estado específico.
  • Outras opções comuns incluem:
    • AddScoped: Uma instância por requisição. Ideal para aplicações web onde o contexto é mantido por requisição (ex.: conexões com bancos de dados).
    • AddSingleton: Uma única instância durante toda a vida útil da aplicação. Indicado para serviços que armazenam estados compartilhados ou configurações globais.
Desta forma, o .NET gerencia automaticamente as dependências para você.

Cuidados ao utilizar a injeção de dependência

Embora a injeção de dependência seja extremamente útil, é importante utilizá-la com bom senso:
  • Em sistemas muito pequenos ou simples, a DI pode introduzir complexidade desnecessária, aumentando a quantidade de código e dificultando o entendimento inicial.
  • O uso abusivo pode levar à criação de classes com muitas dependências, gerando problemas como o anti-pattern conhecido como "constructor over-injection" (excesso de parâmetros no construtor).
  • Avalie cuidadosamente se cada dependência realmente é necessária ou se pode ser simplificada.
Sempre busque equilíbrio: use DI para facilitar, não complicar, seu código

Conclusão

A injeção de dependência é uma técnica essencial para escrever códigos modernos, limpos e sustentáveis. Com ela, você ganha flexibilidade, facilidade de manutenção e eficiência nos testes, preparando-se para crescer como desenvolvedor(a).
🚀
Na formação C# da Rocketseat, você aprende com exemplos práticos, recebe suporte constante e faz parte da maior comunidade de devs da América Latina.
Lembre-se: o futuro da programação pertence a quem se mantém atualizado e pratica constantemente. Bora codar?

Gostou do artigo? Compartilhe com seus colegas e salve nos favoritos para consultas futuras!
Artigos_

Explore conteúdos relacionados

Descubra mais artigos que complementam seu aprendizado e expandem seu conhecimento.

Aprenda programação do zero e DE GRAÇA

No Discover você vai descomplicar a programação, aprender a criar seu primeiro site com a mão na massa e iniciar sua transição de carreira.

COMECE A ESTUDAR AGORA