Injeção de Dependência em C#: Guia Completo com Exemplos

Treinador Online de Python para Iniciantes

Aprenda Python facilmente sem sobrecarga teórica. Resolva tarefas práticas com verificação automática e escreva código diretamente no navegador.

Start Course
Here is the translated HTML content in Portuguese (Português), with all HTML tags preserved and only the text content translated as requested:

Dependency Injection em C#: o que é e para que serve



Dependency Injection (DI) é um dos principais padrões de design que permite criar aplicações em C# com baixo acoplamento e fáceis de testar. Em vez de a classe criar suas próprias dependências (por exemplo, objetos para trabalhar com banco de dados ou logging), essas dependências são passadas (injetadas) de fora. Isso implementa o princípio Inversion of Control (IoC) — o controle é transferido para um contêiner externo.



No ecossistema .NET, o DI se tornou o padrão de fato a partir do ASP.NET Core. O contêiner de dependências embutido (através de Microsoft.Extensions.DependencyInjection) permite registrar e resolver dependências facilmente. Neste artigo, vamos abordar a teoria, exemplos práticos e melhores práticas de uso do DI em C#.



Princípios básicos do Dependency Injection



O DI se baseia em três formas básicas de injeção de dependências. Vamos analisar cada uma delas.



1. Injeção via construtor

A forma mais comum e preferida. As dependências são passadas através dos parâmetros do construtor da classe.



public interface ILogger{    void Log(string message);}

public class ConsoleLogger : ILogger{ public void Log(string message) => Console.WriteLine(message);}

public class OrderService{ private readonly ILogger _logger;

// Injeção de dependência via construtor public OrderService(ILogger logger) { _logger = logger; }

public void ProcessOrder(int orderId) { _logger.Log($"Processando pedido {orderId}"); // lógica de negócio }}


2. Injeção via propriedade

A dependência é definida através de uma propriedade pública. Menos preferível, pois torna a dependência opcional e pode levar a erros em tempo de execução.



public class OrderService{    public ILogger Logger { get; set; }

public void ProcessOrder(int orderId) { if (Logger == null) throw new InvalidOperationException("Logger não foi definido"); Logger.Log($"Processando pedido {orderId}"); }}


3. Injeção via método

A dependência é passada como parâmetro do método. Usada raramente, geralmente para dependências temporárias.



public class OrderService{    public void ProcessOrder(int orderId, ILogger logger)    {        logger.Log($"Processando pedido {orderId}");    }}


Registro de dependências no contêiner .NET



No .NET moderno (ASP.NET Core, Console, Worker Services), é usado o contêiner DI embutido. O registro ocorre no método ConfigureServices ou ao criar um ServiceCollection.



Existem três tempos de vida (lifetime) para serviços registrados:



  • Transient — uma nova instância é criada a cada solicitação. Adequado para serviços leves e de curta duração.
  • Scoped — uma instância por requisição HTTP (ou escopo). Usado para Entity Framework DbContext.
  • Singleton — uma instância para toda a aplicação. Adequado para caches, configurações, loggers.


// Exemplo para ASP.NET Corepublic class Startup{    public void ConfigureServices(IServiceCollection services)    {        // Registro com interface        services.AddTransient<ILogger, ConsoleLogger>();        services.AddScoped<IOrderRepository, OrderRepository>();        services.AddSingleton<IConfiguration, ConfigurationManager>();

// Registro sem interface (classe concreta) services.AddTransient<OrderService>(); }}

// Uso no controllerpublic class OrderController : ControllerBase{ private readonly OrderService _orderService;

public OrderController(OrderServi

Blogs

Book Recommendations