Skip Navigation Links
Novas Tecnologias
Ferramentas Adicionais
Ferramentas Adicionais
Injeção de Dependência (DI) com MVC e Unity
Data:1/29/2012

Translate this page now :





Categories: MVC , ASP.NET

Gostou do texto ? Vote e dê sua opinião! Pontuação atual :
1
Adicione aos Favoritos!
BlogBlogs Rec6 Linkk Ueba Technorati Delicious DiggIt! StumbleUpon

Veja Também


 

A injeção de dependência é uma importante técnica para a sepação de camadas da aplicação, garantindo uma independência entre as camadas.

Em um ambiente web, tal como o ASP.NET MVC, a injeção de dependência carrega alguns desafios muito específicos, porém o Unity.MVC3, uma adaptação do já conhecido Unity para trabalhar com MVC 3, resolve-os com uma considerável facilidade.

Vamos então a um projeto de exemplo de injeção de dependência no MVC 3 com uso de Unity, durante o projeto identificando os desafios, soluções e vantagens da injeção de dependência.

Passo-a-Passo

1) Crie um novo ASP.NET MVC 3 Web Site e selecione a opção Empty Web Site

SNAG-0002

SNAG-0003

2) Na solução, adicione uma Class Library chamada libInterface

3) Na mesma solução, adicione uma Class Library chamada libBLL

SNAG-0005

Explicações

Os controllers da aplicação MVC acessarão as classes de negócio da camada BLL, mas a idéia é que tal acesso seja feito sem criar uma dependência entre ambos. Portanto as interfaces contidas no projeto libInterface são o ponto de relacionamento entre o site (camada de interface) e as classes de negócio.

Importante

É importante que as interfaces fiquem em um projeto isolado, nem no site nem na camada de negócios. Se as interfaces estiverem presas a um ou a outro então isso criará uma dependência indesejável entre ambos e a idéia vai por água abaixo.

Por exemplo, se as interfaces estiverem no site, a camada de negócios dependerá de uma referência ao site para funcionar. Se estiverem na camada de negócios, o site dependerá de uma referência a camada de negócios para funcionar.

4) Faça uma referência no site para a libInterface

SNAG-0007

5) Faça uma referência na libBLL para a libInterface

SNAG-0006

6) Na libInterface crie uma interface chamada ICalculo, conforme o código abaixo.

namespace libInterface
{
    public interface ICalculo
    {
        decimal Calcular(decimal valor1, decimal valor2);
    }
}

7) Na libBLL crie uma classe chamada FazerCalculo conforme o código abaixo

namespace libBLL
{
    public class FazerCalculo : ICalculo 
    {

        public decimal Calcular(decimal valor1, decimal valor2)
        {
            return valor1 * valor2;
        }
    }
}

 

8) No site crie um controller chamado CalculosController

SNAG-0008

Explicações

Nosso desafio é executar a tarefa de calculo no CalculosController sem que o CalculosController tenha conhecimento algum da classe FazerCalculo. A interface ICalculo atua como intermediária.

Importante

Muitos exemplos existentes utilizariam o Unity como service locator e adicionariam na action do controller uma linha como abaixo :

Porém isso é um mal uso da injeção de dependência. Como o nome do pattern já diz, a idéia é que a dependência seja injetada e não que o código da classe vá busca-la. Esse mal uso gera algumas consequencias :

  • Tiramos uma dependência mas adicionamos outra, os testes unitários não serão tão simples.
  • A lógica que deveria ser mais voltada a seu problema fim (executar o cálculo) passa a se preocupar com uma tarefa meio (obter um objeto para executar o cálculo).

A utilização de um container de DI apenas como service locator é considerada um anti-pattern.

9) Criar uma propriedade no controller para conter uma instância de ICalculo (opcionalmente poderia ser uma variável membro da classe)

        ICalculo objCalculo { get; set; }

10) Codificar a action utilizando a propriedade criada

        public ActionResult Index()
        {
            decimal resultado;
            resultado=objCalculo.Calcular(10, 20);

            ViewBag.resultado = resultado;

            return View();
        }

Explicações

Temos nossa action funcionando sem conhecer a classe de negócio, desde que receba com antecedência um objeto que implemente ICalculo – ou seja, desde que seja feita uma injeção da dependência.

11) Crie um construtor no CalculosController conforme o código abaixo :

        public CalculosController(ICalculo calculo)
        {
            objCalculo = calculo;
        }

Explicações

Para o Unity o parâmetro no construtor funciona como indicação de dependência e quando pedirmos ao Unity para resolver as dependências ele injetará a classe FazerCalculo conforme desejado, permitindo a nosso controller funcionar.

Em simples classes isso seria fácil, mas em um controller do MVC isso guarda um desafio adicional : É o ASP.NET MVC que instancia os controllers, não nós. Então deverá ser o ASP.NET MVC a identificar a dependência e permitir a injeção.

Felizmente isso é um recurso presente no ASP.NET MVC 3 e o Unity.MVC se integra a ele.

Importante

Estamos falando do Unity, mas de fato nesses passos ainda não incluimos o Unity como parte do nosso projeto.

12) Clique com o botão direito no projeto e utilize Add Library Package. Selecione a opção “online” e pesquise pelo Unity.MVC. Poderá então adicionar o Unity.MVC ao projeto.

 

SNAG-0011

Explicação

A inclusão de bibliotecas, frameworks e ferramentas de terceiros em nossos projetos se tornou tão comum que foi criado um formato de pacotes para facilitar a inclusão e exclusão de tais recursos de nossos projetos.

Quando o Unity.MVC é adicionado, são baixadas DLLs e outros arquivos da internet. As DLLs são adicionadas nas referências de nosso projeto e os outros arquivos, em especial o Bootstraper.cs, são adicionados ao projeto.

É também adicionado ao projeto um arquivo packages.config, que registra os packages adicionados ao nosso projeto, facilitando sua remoção quando desejarmos.

13) No global.asax, no application_start, adicione a linha abaixo como última linha do application_start

        protected void Application_Start()
        {
            AreaRegistration.RegisterAllAreas();

            RegisterGlobalFilters(GlobalFilters.Filters);
            RegisterRoutes(RouteTable.Routes);

            Bootstrapper.Initialise();
        }

Explicação

O Unity.MVC é muito pouco invasivo, feito realmente para pouco notarmos sua presença. Essa linha mais o arquivo Bootstraper.cs são as únicas adições ao projeto (sem contar as references, claro), afetando assim mínimamente o nosso código

Analisando o Bootstraper.cs

Ao abrir o arquivo você observará a presença de uma rotina chamada BuildUnityContainer, que cria uma instância da classe UnityContainer e a configura.

No método Initialise, que chamamos a partir do application_start, verá que o unity container é construido (chamando-se a BuildUnityContainer) e é utilizada uma linha adicional, a chave do funcionamento do Unity com MVC :

A classe DependencyResolver é um recurso fornecido pelo MVC 3 que nos permite fornecer ao MVC um container de service locator. Com esse container o MVC passa a realizar a resolução de dependências dos controllers.

    public static class Bootstrapper
    {
        public static void Initialise()
        {
            var container = BuildUnityContainer();

            DependencyResolver.SetResolver(new UnityDependencyResolver(container));
        }

        private static IUnityContainer BuildUnityContainer()
        {
            var container = new UnityContainer();

            // register all your components with the container here
            // e.g. container.RegisterType();            

            container.RegisterType();            

            container.RegisterControllers();

            return container;
        }
    }

14) Adicione no projeto do site uma referência para o projeto libBLL.

15) No arquivo bootstraper.cs, no método BuildUnityContainer, antes da chamada de RegisterControllers, adicione a seguinte linha :

            container.RegisterType(); 

Explicação

Com isso estamos apresentando nossa classe concreta – FazerCalculo – para o UnityContainer, indicando que a classe implementa a interface ICalculo e deve ser utilizada sempre que for solicitado ao UnityContainer uma instância de ICalculo.

Importante

Nenhum dos dois passos, 14 e 15, não são realmente desejáveis na prática do uso da DI, pois criamos uma dependência de design-time entre o projeto do site e o projeto da camada de negócios.

Na prática existe outra solução, mas ficará para o próximo post. Deixaremos estes passos aqui como uma solução mais didática.

16) Clique com o botão direito sobre a action Index do CalculosController e crie uma view.

17) Na view, adicione o seguinte código :

@{
    ViewBag.Title = "Index";
}

<h2>Index</h2>

Resultado : @ViewBag.resultado

18) Rode a aplicação. Poderá observar o resultado do cálculo sendo exibido na página.

Explicação

Com isso fica demonstrado que o código em nosso CalculosController chegou a seu resultado sem instanciar nenhuma classe (não fez new) e sem conhecer a classe da camada de negócio (FazerCalculo).

O CalculosController recebeu a injeção de uma instância do FazerCalculo a partir do UnityContainer.



Categories: MVC , ASP.NET


Nome :
E-mail:
Comentarios :
 
 
Os Últimos Comentários
data: 10/14/2016 2:04:00 PM
nome: GnHCxYqCGpMBqZJxD
email: jimos4581rzt@hotmail.com
comentário:
mP6y1J http://www.FyLitCl7Pf7kjQdDUOLQOuaxTXbj5iNG.com

data: 10/14/2016 1:48:00 PM
nome: qeuqQvKKTGYN
email: jimos4581rzt@hotmail.com
comentário:
uiJiSE http://www.FyLitCl7Pf7kjQdDUOLQOuaxTXbj5iNG.com

data: 8/6/2016 7:18:00 PM
nome: KvoOYeoCbTPYLwTcg
email: jimos4581rt@hotmail.com
comentário:
6ZcVOY http://www.FyLitCl7Pf7kjQdDUOLQOuaxTXbj5iNG.com

 1  
Dicas
Dica do Dia
Receba Dicas Por Email
E-mail :  
 


 (help)
Aceito receber informativos do devASPNet, informações de eventos e treinamentos

Veja Quais Informativos Você Receberá

Pesquisar Dicas
Pesquisar Artigos, Dicas e Noticias

Banco de Dados
Algumas Entrevistas
Links Importantes

Búfalo Informática, Treinamento e Consultoria
R. Alvaro Alvim, 37/920 Centro - Cinelândia - Rio de Janeiro Cep: 20031-010
Tel : (21) 2262-1368 (21) 9240-5134 E-mail : Contato@bufaloinfo.com.br