Em um dado post falamos sobre a injeção de dependência, e como ela atua como uma das formas de inversão de controle e como utilizar estes conceitos. O Unity é um framework de injeção de dependência lançado em 2008 pela Microsoft, o Unity nasceu com o propósito de nos auxiliar no desacoplamento de classes, manter uma arquitetura mais “plugável”, e além destes benefícios, ele facilita a criação de testes unitários, por deixar as camadas mais desacopladas .
O Unity é parte da Enteprise Library, mas pode também ser utilizado sem ela. Ele é um container de injeção de dependência, que tem a responsabilidade de resolver as dependências em uma hierarquia de classes, ou seja, ele vai verificar as dependências e construir os objetos baseado nas mesmas. O Unity também pode ser usado para interceptação, no caso de quem trabalha no estilo AOP. Ele pode resolver uma cadeia de dependências inteira como também resolver as dependências de objetos que não foram construídos por ele. Observe a figura abaixo:

A figura acima mostra o processo de injeção de dependência que o unity pode fazer. Ele trabalha com três tipos de injeção: injeção por construtor ( constructor injection), injeção por propriedade ( setter injection) e embora ele trabalhe com injeção por chamada de método, ele não dá suporte à interface injection, que Martin Fowler falava em seu artigo sobre inversão de controle e DI. Vejamos a descrição de como o Unity trabalha com cada uma delas:
Injeção por construtor (constructor injection ): Este tipo de injeção ocorre automaticamente. Quando você cria um objeto utilizando um container do Unity, ele gera instâncias para cada um dos parâmetros especificados na assinatura do construtor, registrando e mapeando a classe de cada objeto no container.
Injeção por propriedade (Setter Injection ): Este tipo de injeção é opcional. Você pode adicionar o atributo Dependecy para cada uma das propriedades que você deseja que o Unity resolva através do container. Exemplo:
public class BancoDadosWrapper { [ Dependency ] public ILog Log { get; set; } }
Injeção po chamada de método: Este tipo de injeção também é opcional. Você pode adicionar o atributo InjectionMethod para cada um dos métodos que deseja que o Unity venha resolver através do container. O Unity verificará os parâmetros do método e retornará uma instância da classe que resolve o tipo de cada um dos parâmetros. Ele é úti, quando queremos ter métodos de inicialização para um objeto específico. Exemplo:
public class BancoDados { private ILog __fobjLog; [ InjectionMethod ] public void Inicializar( ILog pobjLog ) { this.__fobjLog = pobjLog; } }
Talvez, você pode estar se perguntando: como o Unity sabe qual classe implementa determinada interface? Como ele acha a classe que herda de uma determinada classe abstrata? É justamente aí que entra a configuração no Unity.
Configuração
O Unity precisa ser configurado, e há até aqueles que acham que isto é um ponto negativo para ele. A necessidade da configuração se dá porque você precisa mapear as abstrações ( interfaces ou classes abstratas) para suas implementações, ou seja, suas classes concretas, para que o unity possa resolver a dependência quando a mesma for solicitada. A confguração pode se feita por arquivo de configuração (web.config, por exemplo ), ou em runtime via código, programaticamente. Segue abaixo um exemplo de cada tipo de configuração:
Via arquivo web.config
É necesário adicionar a section abaixo e configurar o container:
<configSections> <section name="unity" type="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection, Microsoft.Practices.Unity.Configuration"/> </configSections>
Configuração do container:
<containers> <container name="containerDI"> <types> <type type="ILog" mapTo="LogBancoDados" /> </types> </container>
Programaticamente, a configuração é realizada utilizando-se o método RegisterType da classe UnityContainer.
var objContainer = new UnityContainer(); objContainer.RegisterType<ILog, LogBancoDados>();
Uma vez configurado, é muito fácil utilizar o Unity. Quando você quiser um objeto que implementa uma determinada abstração, é só chamar o método Resolve da classe UnityContainer.
var objContainer = new UnityContainer(); objContainer.Resolve<ILog>();
Vejamos agora um exemplo em que o Unity funciona como container de DI em uma classe que implementa um pattern de arquitetura, chamado Registry. Observe a classe abaixo:
public class Registry { private IUnityContainer __fobjContainerDI; protected static Registry __fobjinstancia; public Registry() { } public Registry(bool setup) { this.__fobjContainerDI = new UnityContainer(); this.__fobjContainerDI.RegisterType<ILog, LogBancoDados>(); this.__fobjContainerDI.RegisterType<IGerenciaExcecao, GerenciaExcecao>(); } protected static Registry Instancia { get { if (_instancia == null) _instancia = new Registry(true); return _instancia; } } public static ILog getLog() { return this.__fobjContainerDI.Resolve<ILog>(); } public static IGerenciaExcecao getGerenciadorExcecao() { return this.__fobjContainerDI.Resolve<IGerenciaExcecao>(); } }
No caso da classe mostrada acima, no construtor da mesma instanciamos um container do Unity. Após termos feito isto, registramos uma implementação para a interface Ilog e outra para a interface IGerenciaExcecao. Quando for utilizado o método getLog ou getGerenciadorExcecao, o container do Unity retornará para a classe que chamar o método um objeto da classe que implementa a interface Ilog ou IGerenciaExcecao, mostrando assim como se inverte o controle, ou seja, ao invés de depender de uma classe concreta, esta dependência passa a estar na direção oposta, apontando para uma abstração.
Pessoal, espero tê-los ajudado, de alguma maneira, a entender como utilizar o conceito de injeção de dependência e o Unity Application Block. O Unity é um framework fácil de usar, configurar e atende muito bem quando se quer utilizar IoC ( Inversion of Control ) em um projeto, obtendo uma arquitetura mais limpa e desacoplada. Até a próxima, com mais conteúdo sobre arquitetura e afins.