(Relacionado a esta pergunta, EF4: Por que a criação de proxy precisa ser ativada quando o carregamento lento está ativado? ).
Eu sou novo no DI, então tenha paciência comigo. Entendo que o contêiner é responsável por instanciar todos os meus tipos registrados, mas para isso, é necessário fazer referência a todas as DLLs da minha solução e suas referências.
Se eu não estivesse usando um contêiner de DI, não precisaria fazer referência à biblioteca EntityFramework no meu aplicativo MVC3, apenas minha camada de negócios, que faria referência à minha camada DAL / Repo.
Sei que no final do dia todas as DLLs estão incluídas na pasta bin, mas meu problema é ter que fazer referência explícita a ela através de "add reference" no VS para poder publicar um WAP com todos os arquivos necessários.
Respostas:
Sim, é exatamente a situação que a DI trabalha tanto para evitar :)
Com código fortemente acoplado, cada biblioteca pode ter apenas algumas referências, mas estas novamente têm outras referências, criando um gráfico profundo de dependências, como este:
Uma vez que o gráfico de dependência é profunda, que significa que a maioria das bibliotecas arrastar ao longo de uma série de outras dependências - por exemplo, no diagrama, Biblioteca C arrasta Biblioteca H, Biblioteca E, Biblioteca J, Biblioteca H, Biblioteca K e Biblioteca N . Isso dificulta a reutilização de cada biblioteca independentemente do restante - por exemplo, em testes de unidade .
No entanto, em um aplicativo fracamente acoplado, movendo todas as referências para a Raiz da Composição , o gráfico de dependência é achatado severamente :
Conforme ilustrado pela cor verde, agora é possível reutilizar a Biblioteca C sem arrastar as dependências indesejadas.
No entanto, tudo isso dito, com muitos DI Containers, você não precisa adicionar referências concretas a todas as bibliotecas necessárias. Em vez disso, você pode usar a ligação tardia na forma de varredura de montagem baseada em convenção (preferencial) ou configuração XML.
Ao fazer isso, no entanto, lembre-se de copiar os assemblies para a pasta bin do aplicativo, porque isso não acontece mais automaticamente. Pessoalmente, raramente acho que vale a pena esse esforço extra.
Uma versão mais elaborada dessa resposta pode ser encontrada neste trecho do meu livro Injection Dependency, Principles, Practices, Patterns .
fonte
Mesmo ao usar um contêiner de DI, você não precisa permitir que seu projeto MVC3 faça referência à EF, mas você (implicitamente) escolhe fazer isso implementando a Raiz de Composição (o caminho de inicialização onde você compõe seus gráficos de objeto) dentro de seu projeto MVC3. Se você for muito rigoroso quanto à proteção de seus limites de arquitetura usando montagens, poderá mover sua lógica de apresentação para um projeto diferente.
Quando você move toda a lógica relacionada ao MVC (controladores, etc.) do projeto de inicialização para uma biblioteca de classes, ele permite que esse conjunto da camada de apresentação fique desconectado do restante do aplicativo. Seu próprio projeto de aplicativo da Web se tornará um shell muito fino com a lógica de inicialização necessária. O projeto de aplicativo da Web será a Raiz da Composição que referencia todos os outros assemblies.
Extrair a lógica de apresentação para uma biblioteca de classes pode complicar as coisas ao trabalhar com o MVC. Será mais difícil conectar tudo, pois os controladores não estão no projeto de inicialização (enquanto visualizações, imagens, arquivos css provavelmente devem permanecer no projeto de inicialização). Provavelmente isso é possível, mas levará mais tempo para configurar.
Por causa das desvantagens, geralmente aconselho manter apenas a raiz da composição no projeto da web. Muitos desenvolvedores não querem que seu assembly MVC dependa do assembly DAL, mas isso não é realmente um problema. Não esqueça que montagens são um artefato de implantação ; você divide o código em vários assemblies para permitir que o código seja implantado separadamente. Uma camada arquitetônica, por outro lado, é um artefato lógico . É muito possível (e comum) ter várias camadas na mesma montagem.
Nesse caso, teremos a raiz da composição (camada) e a camada de apresentação no mesmo projeto de aplicativo da web (portanto, no mesmo assembly). E mesmo que esse assembly faça referência ao assembly que contém o DAL, a camada de apresentação ainda não faz referência à camada de acesso a dados . Esta é uma grande distinção.
Obviamente, quando fazemos isso, perdemos a capacidade do compilador de verificar essa regra de arquitetura em tempo de compilação, mas isso não deve ser um problema. A maioria das regras de arquitetura não pode ser verificada pelo compilador e sempre há algo como bom senso. E se não houver senso comum em sua equipe, você sempre poderá usar revisões de código (que toda equipe deve IMO sempre fazer). Você também pode usar uma ferramenta como o NDepend (que é comercial), que ajuda a verificar suas regras de arquitetura. Quando você integra o NDepend ao seu processo de construção, ele pode avisá-lo quando alguém fizer o check-in de um código que viole essa regra de arquitetura.
Você pode ler uma discussão mais elaborada sobre como a Raiz da Composição funciona no capítulo 4 do meu livro Injeção de Dependência, Princípios, Práticas, Padrões .
fonte
Você pode criar um projeto separado chamado "DependencyResolver". Neste projeto, você deve fazer referência a todas as suas bibliotecas.
Agora, a camada de interface do usuário não precisa de NHibernate / EF ou qualquer outra biblioteca não relevante para a interface do usuário, exceto Castle Windsor para ser referenciada.
Se você deseja ocultar Castle Windsor e DependencyResolver da camada da interface do usuário, você pode escrever um HttpModule que chama o material de registro IoC.
Eu tenho apenas um exemplo para StructureMap:
O DefaultControllerFactory não usa o contêiner de IoC diretamente, mas delega para os métodos de contêiner de IoC.
O
GetController
delegado é definido em um registro do StructureMap (em Windsor, deve ser um instalador).fonte
fonte