Injeção de dependência (Dependency Injection, em inglês) é um padrão de desenvolvimento utilizado quando é necessário manter baixo o nível de acoplamento entre diferentes módulos de um sistema. Nesta solução as dependências entre os módulos não são definidas programaticamente, mas sim pela configuração de uma infraestrutura de software (container) que é responsável por “injetar” em cada componente suas dependências declaradas. A Injeção de dependência se relaciona com o padrão Inversão de controle mas não pode ser considerada um sinônimo deste.

Existem vários Frameworks para realizar a injeção de dependência em C#, dentre os principais posso citar o Spring.Net e o Ninject.  O Spring vai mais além do que um simples framework de injeção de dependência, e para quem às vezes deseja somente realizar a injeção de dependência pode acabar tentando matar uma formiga com uma bala de canhão, o Ninject surgiu para facilitar esse conceito, nada de mágica, nada de configuração xml e etc, ele pode ser uma boa saída para quem deseja algo simples e limpo.

Mas enfim, no Framework 4 existem algumas classes disponibilizadas no assembly System.ComponentModel.Composition que podemos utilizar de forma que eu não precisamos referenciar classes de terceiros em nossos projetos ou até mesmo criar aquelas configurações mirabolantes em xml.

Veja o código abaixo, perceba que em nenhum momento as propriedades MeuComponente e Mensagem são instanciados, mas no momento da execução da aplicação o .net injeta através do container, utilizando a interface e dos atributos export e import, a classe com a implementação da interface. Lembrado que podemos utilizar dessa tecnologia para criação de software componentizados, softwares baseado em plugins dentre outros modelos de arquitetura.

[code] using System;
using System.ComponentModel.Composition;
using System.ComponentModel.Composition.Hosting;
using System.Reflection;

namespace InjecaoDependencia
{
class Program
{
[Import] public IMyComponent MeuComponente { get; set; }

[Import] public IPrintMessage Mensagem { get; set; }

static void Main(string[] args)
{
var p = new Program();
p.Run();
}

public void Run()
{
var assembly = new AssemblyCatalog(Assembly.GetExecutingAssembly());
var container = new CompositionContainer(assembly);
container.ComposeParts(this);

Mensagem.Imprime("Hello World");

Console.WriteLine(MeuComponente.SomaNumeros(5, 7));
Console.WriteLine(MeuComponente.MultiplicaNumeros(5, 7));
}
}

public interface IPrintMessage
{
void Imprime(String mensagem);
}

public interface IMyComponent
{
int SomaNumeros(int a, int b);
int MultiplicaNumeros(int a, int b);
}

[Export(typeof(IPrintMessage))] public class PrintMessage : IPrintMessage
{

public void Imprime(String mensagem)
{
Console.WriteLine(mensagem);
}
}

[Export(typeof(IMyComponent))] public class MeuComponente : IMyComponent
{
public int SomaNumeros(int a, int b)
{
return a + b;
}

public int MultiplicaNumeros(int a, int b)
{
return a * b;
}
}
}
[/code]

2 Comentários. Deixe novo

  • Belo artigo, Clóvis!
    Explicação simples e direta, sem firulas =)
    O bom dessa abordagem é evitar um construtor mais complexo, com várias dependências.

    Responder
  • Israel Branco
    11/04/2011 17:45

    Grande Clovis,

    Parabéns pelo artigo. Fiquei com uma dúvida: Por exemplo, se tivermos 2 classes que implementam a interface IMyComponent, como o interpretador saberá qual das duas classes ele deve injetar? Temos alguma outra informação para passar ao interpretador para que ele saiba qual classe concreta nos queremos em cada momento (similar ao Spring).

    Grande abraço.

    Responder

Deixe uma resposta

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *

Preencha esse campo
Preencha esse campo
Digite um endereço de e-mail válido.
Você precisa concordar com os termos para prosseguir

Menu