Injeção de Dependência com MS Unity

Filed Under (.NET, Boas Práticas, Patterns) by Vinicius Quaiato on 18-01-2010

Tagged Under : , , , ,

Bom pessoal, pudemos ver os benefícios e alguns usos de Inversão de Controle e Injeção de Dependências aqui e aqui.

Uma das formas de obter excelentes ganhos com a inversão de controle é através da utilização de um contêiner de Injeção de Dependências.

Um contêiner de injeção de dependências é capaz de criar objetos com todas suas dependências injetadas e totalmente pronto para uso. Em geral estes conteiners podem ser configurados manualmente(programaticamente) ou dinamicamente(através de arquivos de configuração por exemplo).

Falaremos um pouco do Unity que é um contêiner de Injeção de Dependência que faz parte dos Application Blocks da Microsoft.

Para que vejamos como o Unity funciona faça o download do mesmo aqui e execute o setup, que irá apenas criar uma pasta com as DLLs do Unity.

O Unity, como veremos nos exemplos, suporta 3 tipos de injeção de dependência:

  • Constructor Injection (injeção por construtor)
  • Property Injection (injeção de propriedade)
  • Method Call Injection (injeção de chamada de métodos)

Vamos usar como exemplo estas classes e interfaces:

public interface ILogger
{
    void RegistrarMensagem(string mensagem);
}
 
public class SqlLogger : ILogger
{
    public void RegistrarMensagem(string mensagem)
    {
        //abre conexão SQL
 
        //Executa insert da mensagem
    }
}
 
public class EnviadorDeEmails
{
    public ILogger Logger { get; set; }
    public EnviadorDeEmails(ILogger logger)
    {
        this.Logger = logger;
    }
    public void EnviarEmail(string email, string mensagem)
    {
        //Envia email
 
        //registra envio
        this.Logger.RegistrarMensagem(string.Format("Email enviado para {0}", email));
    }
}

Adicione as seguintes referências ao seu projeto: Microsoft.Practices.ObjectBuilder2.dll e Microsoft.Practices.Unity.dll que se encontram na pasta que você “instalou” o Unity, como pode ser visto na figura abaixo:
Incluindo Dlls do Unity

As classes acima são bem simples, no final das contas o que faremos é com que o Unity crie um EnviadorDeEmails com a dependência de ILogger injetada e resolvida, ou seja, que ele crie um EnviadorDeEmails passando para ele um SqlLogger. Para isso vamos “ensinar” ao Unity como resolver a interface ILogger, como pode ser visto no código abaixo:

1
2
    var unityContainer = new UnityContainer();
    unityContainer.RegisterType<ILogger, SqlLogger>();

Na linha 1 criamos uma instância do contêiner do Unity. Na linha 2 dizemos para o Unity que quando quisermos o tipo ILogger (interface) ele deve utilizar a classe concreta SqlLogger. Simples assim.

Constructor Injection

Agora podemos mandar que o Unity construa nosso EnviadorDeEmails usando constructor injection, conforme visto abaixo:

1
2
3
4
5
6
7
8
9
10
[TestMethod]
public void Configurando_Unity_Para_Resolver_ILogger()
{
    var unityContainer = new UnityContainer();
    unityContainer.RegisterType<ILogger, SqlLogger>();
 
    var enviadorEmails = unityContainer.Resolve<EnviadorDeEmails>();
 
    Assert.IsInstanceOfType(enviadorEmails.Logger, typeof(SqlLogger));
}

O grande segredo aí está na linha 7 onde dizemos para o Unity construir nosso EnviadorDeEmails. O Unity percebe que existe uma dependência no construtor do EnviadorDeEmails, e baseado na configuração que fizemos ele sabe como resolver esta dependência. Na linha 9 apenas verificamos se de fato o ILogger utilizado é o SqlLogger, e executando o teste obtemos sucesso.
E notem que neste caso utilizamos o constructor injection pois a classe EnviadorDeEmails possui um construtor com uma dependência para uma interface, que o Unity conhece.

Property Injection

Poderíamos dizer que a dependência não deve ser resolvida via construtor, mas sim diretamente na propriedade, para isso alteraríamos a classe EnviadorDeEmails assim:

1
2
3
4
5
6
7
8
9
10
11
12
public class EnviadorDeEmails
{
    [Dependency]
    public ILogger Logger { get; set; }
    public void EnviarEmail(string email, string mensagem)
    {
        //Envia email
 
        //registra envio
        this.Logger.RegistrarMensagem(string.Format("Email enviado para {0}", email));
    }
}

A única diferença aqui foi a utilização do DependencyAttribute na linha 3 para marcar que a propriedade Logger, do tipo ILogger, deve ser resolvida pelo Unity.
Executando nosso teste mais uma vez devemos obter sucesso.

Method Call Injection

A outra forma que o Unity tem para injetar nossas dependências é através da chamada de um método. Por exemplo, imaginem que temos um método Initialize na nossa classe, que é responsável por criar os objetos que nossa classe precisa. Podemos fazer com que o Unity execute este método resolvendo todas as dependências.
Vejamos o código da classe EnviadorDeEmails utilizando um Method Call Injection:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class EnviadorDeEmails
{
    public ILogger Logger { get; set; }
    public void EnviarEmail(string email, string mensagem)
    {
        //Envia email
 
        //registra envio
        this.Logger.RegistrarMensagem(string.Format("Email enviado para {0}", email));
    }
 
    [InjectionMethod]
    public void Inicializador(ILogger logger)
    {
        this.Logger = logger;
    }
}

Tudo o que fizemos desta vez foi criar um método, neste caso o método Inicializador, na linha 13, que recebe como parâmetros as dependências da nossa classe. E marcamos este método com o InjectionMethodAttribute, para dizer ao Unity que este método deve ser chamado e resolvidor por ele na criação de nosso EnviadorDeEmails.
E novamente se executarmos o mesmo método de teste, obteremos sucesso.

Como vimos nos três exemplos acima, o Unity após configurado consegue resolver as dependências de nossas classes de forma simples e trivial. Basta alterarmos a forma de resolução da dependência, por exemplo de constructor para setter, e nada no código mudará, assim como se mudar de SqlLogger para XmlLogger, nada no código mudará, apenas a configuração do Unity.

Bom galera, é mais ou menos isso. O Unity é uma ferramenta bastante poderosa, extensível e simples de usar.

Qualquer dúvida é só escrever nos comentários ou enviar email.

Abraços,
Vinicius Quaiato.

Injeção de Dependência no C#

Filed Under (.NET, Boas Práticas, Patterns) by Vinicius Quaiato on 21-12-2009

Tagged Under : , , , , ,

Hoje vamos falar um pouco sobre Injeção de Dependências no C#.

Injeção de Dependência é uma das formas de obter Inversão de Controle.

O nome já diz quase tudo, quando uma classe possui dependência de alguma outra classe concreta, devemos então criar uma dependência para uma interface, ou seja, uma abstração.
Com nossa classe dependendo de uma abstração, nós injetamos um objeto concreto nela.

É um conceito bastante simples, vamos entender com um pouco de código.

A classe abaixo é uma classe de acesso ao banco de dados. Ela é responsável por executar um comando SQL apenas:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
public class SqlClass
{
    public void ExecutarComando(string comando)
    {
        try
        {
            using (SqlConnection conexao = new SqlConnection("CONNECTION STRING"))
            {
                using (SqlCommand comandoSql = conexao.CreateCommand())
                {
                    comandoSql.CommandText = comando;
                    comandoSql.CommandType = CommandType.Text;
 
                    comandoSql.ExecuteNonQuery();
                }
            }
        }
        catch (SqlException sqlEx)
        {
            new LogErros().RegistrarArquivoTexto(sqlEx.Message);
 
            throw sqlEx;
        }
    }
}

Qual o problema desta classe? Simples, ela depende de uma classe concreta de log, como pode ser visto na linha 20.

O que podemos fazer para resolver este problema?
Em primeiro lugar precisamos extrair uma interface para a geração de logs, teríamos uma interface mais ou menos assim:

public interface ILogErros
{
    void RegistrarErro(string mensagemDeErro);
}

Agora fazemos nossa classe de banco de dados conhecer esta interface e criar uma forma de ter um objeto que implemente esta interface injetado:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
public class SqlClass
{
    private ILogErros logErros = null;
 
    public SqlClass(ILogErros objetoLog)
    {
        this.logErros = objetoLog;
    }
 
    public void ExecutarComando(string comando)
    {
        try
        {
            using (SqlConnection conexao = new SqlConnection("CONNECTION STRING"))
            {
                using (SqlCommand comandoSql = conexao.CreateCommand())
                {
                    comandoSql.CommandText = comando;
                    comandoSql.CommandType = CommandType.Text;
 
                    comandoSql.ExecuteNonQuery();
                }
            }
        }
        catch (SqlException sqlEx)
        {
            logErros.RegistrarErro(sqlEx.Message);
 
            throw sqlEx;
        }
    }
}

Na linha 3 criamos um campo na classe do tipo da interface. É importante perceber que agora nossa classe de banco de dados não conhece o objeto de log, ela apenas conhece sua interface. Ela não sabe como o log será gravado.
Nas linhas 5 a 8 criamos um construtor que recebe um objeto que implementa a interface ILogErros, e este construtor irá garantir que quem quer que instancie a classe tenha que injetar um objeto de log para ela. E isto é Injeção de Dependências!

Este tipo de injeção de dependência é conhecido como Constructor Injection, ou seja, injeção via construtor.

Agora para que consigamos instanciar nossa classe SqlClass precisamos passar um objeto que implemente ILogErros, algo mais ou menos assim:

SqlClass sql = new SqlClass(new LogEmArquivoTexto());

Onde LogEmArquivoTexto implementa ILogErros.

Podemos usar o recurso de Inversão de Controle visto aqui para criarmos uma factory que já nos retorne um objeto SqlClass com a dependência injetada, nos poupando algum trabalho.

E no próximo post veremos como utilizar o Unity, um contêiner de injeção de dependências da Microsoft.

Abraços galera, espero que tenham gostado.
Qualquer dúvida é só escrever.

Att,
Vinicius Quaiato.

Inversão de Controle (Inversion of Control / IoC)

Filed Under (.NET, Boas Práticas, Patterns) by Vinicius Quaiato on 09-12-2009

Tagged Under : , , , , ,

Fala galera, beleza?
Escolhi falar de Inversão de Controle pois recentemente precisei utilizar este conceito em uma nova implementação no trabalho. E também percebi o quão necessário é que os desenvolvedores conheçam este conceito/padrão/técnica.

Bom vamos lá.
Inversão de Controle, como o próprio nome diz significa que o controle de execução do programa/código muda. Eu gosto de pensar também que o controle de conhecimento do código muda.

Como isso?
De uma forma bem simplista podemos dizer por exemplo que o controle que uma classe/método possui acaba sendo mudado, invertido, para algum outro ponto do código.

Vamos ver um exemplo de código:

1
2
3
4
5
6
7
8
9
10
11
12
public class Pedido
{
    private EnviadorDeEmails enviador = null;
 
    public void Gravar()
    {
        //Vai ao banco de dados
 
        this.enviador = new EnviadorDeEmails("smtp","conta@empresa.com","senha");
        this.enviador.EnviarEmail("Novo Pedido Criado!");
    }
}

Esta classe possui não somente o controle do fluxo de execução do programa, mas ela possui o controle sobre o código, e isso significa alto acoplamento e responsabilidades demais.
Ela sabe exatamente como criar um EnviadorDeEmails, e controla também os parâmetros de configuração do smtp.
Ainda que ela recuperasse estes valores do arquivo .config ou do banco de dados, ela teria esse controle.

Como poderíamos, de forma simples, inverter este controle? Uma maneira simples e eficaz seria utilizando um Factory Method estático, na própria classe EnviadorDeEmails, vejamos como ficaria:

1
2
3
4
5
6
7
8
public static EnviadorDeEmails ObterEnviadorDeEmails()
{
    //valores podem vir do .config
    //podem vir do banco
    //quem consome esta classe não sabe
    //ela não tem controle sobre isso
    return new EnviadorDeEmails("smtp", "email@empresa.com", "senha");
}

E então nossa classe Pedido ficaria assim:

1
2
3
4
5
6
7
8
9
10
11
12
public class Pedido
{
    private EnviadorDeEmails enviador = null;
 
    public void Gravar()
    {
        //Vai ao banco de dados
 
        this.enviador = EnviadorDeEmails.ObterEnviadorDeEmails();
        this.enviador.EnviarEmail("Novo Pedido Criado!");
    }
}

É isso pessoal.
Esta é uma das muitas maneiras de realizar Inversão de Controle.
Como Martin Fowler explica, uma outra forma de IoC seria utilizando Template Methods. A classe abstrata define o fluxo de controle, mas o que será executado é o código cliente quem define, e assim o controle é novamente invertido.

Poderíamos fazer isso utilizando Injeção de Dependências, e Contêiners de IoC/DI.
Nos próximos posts falaremos mais sobre Injeção de Dependências e Contêiners de IoC.

Martin Fowler tem um texto clássico sobre este assunto: http://martinfowler.com/bliki/InversionOfControl.html

Abraços.
Vinicius Quaiato.