(Relacionado con esta pregunta, EF4: ¿Por qué la creación de proxy tiene que habilitarse cuando la carga diferida está habilitada? ).
Soy nuevo en DI, así que tengan paciencia conmigo. Entiendo que el contenedor se encarga de crear instancias de todos mis tipos registrados, pero para hacerlo requiere una referencia a todas las DLL en mi solución y sus referencias.
Si no estuviera usando un contenedor DI, no tendría que hacer referencia a la biblioteca EntityFramework en mi aplicación MVC3, solo a mi capa empresarial, que haría referencia a mi capa DAL / Repo.
Sé que al final del día todas las DLL están incluidas en la carpeta bin, pero mi problema es tener que hacer referencia explícitamente a través de "agregar referencia" en VS para poder publicar un WAP con todos los archivos necesarios.
Respuestas:
Sí, esa es exactamente la situación que DI trabaja tan duro para evitar :)
Con un código estrechamente acoplado, cada biblioteca puede tener solo unas pocas referencias, pero estas nuevamente tienen otras referencias, creando un gráfico profundo de dependencias, como este:
Debido a que la gráfica de dependencia es profundo, que significa que la mayoría de bibliotecas arrastran a lo largo de una gran cantidad de otras dependencias - por ejemplo, en el diagrama, Biblioteca C arrastra a lo largo Biblioteca H, Biblioteca E, Biblioteca J, Biblioteca M, Biblioteca K y Biblioteca N . Esto hace que sea más difícil reutilizar cada biblioteca independientemente del resto, por ejemplo, en pruebas unitarias .
Sin embargo, en una aplicación débilmente acoplada, al mover todas las referencias a la raíz de composición , el gráfico de dependencia se aplana severamente :
Como lo ilustra el color verde, ahora es posible reutilizar la Biblioteca C sin arrastrar las dependencias no deseadas.
Sin embargo, todo lo dicho, con muchos contenedores DI, no tiene que agregar referencias duras a todas las bibliotecas requeridas. En cambio, puede usar el enlace tardío en forma de escaneo de ensamblaje basado en convenciones (preferido) o configuración XML.
Sin embargo, cuando haga eso, debe recordar copiar los ensamblajes en la carpeta bin de la aplicación, porque eso ya no ocurre automáticamente. Personalmente, rara vez encuentro que valga la pena ese esfuerzo extra.
Se puede encontrar una versión más elaborada de esta respuesta en este extracto de mi libro Dependency Injection, Principles, Practices, Patterns .
fuente
Incluso cuando usa un contenedor DI, no tiene que dejar que su proyecto MVC3 haga referencia a EF, sino que (implícitamente) elige hacer esto implementando la raíz de composición (la ruta de inicio donde compone sus gráficos de objetos) dentro de su proyecto MVC3. Si es muy estricto sobre la protección de sus límites arquitectónicos mediante el uso de ensamblajes, puede mover su lógica de presentación a un proyecto diferente.
Cuando mueve toda la lógica relacionada con MVC (controladores, etc.) del proyecto de inicio a una biblioteca de clases, permite que este ensamblaje de capa de presentación permanezca desconectado del resto de la aplicación. El proyecto de su aplicación web se convertirá en un shell muy delgado con la lógica de inicio requerida. El proyecto de aplicación web será la raíz de composición que hace referencia a todos los demás ensamblados.
Extraer la lógica de presentación a una biblioteca de clases puede complicar las cosas cuando se trabaja con MVC. Será más difícil conectar todo, ya que los controladores no están en el proyecto de inicio (mientras que las vistas, imágenes, archivos CSS, probablemente deben permanecer en el proyecto de inicio). Esto probablemente sea factible, pero llevará más tiempo configurarlo.
Debido a las desventajas, generalmente aconsejo mantener la raíz de composición en el proyecto web. Muchos desarrolladores no quieren que su ensamblaje MVC dependa del ensamblaje DAL, pero eso no es realmente un problema. No olvide que los ensamblajes son un artefacto de implementación ; divide el código en múltiples ensamblajes para permitir que el código se implemente por separado. Una capa arquitectónica, por otro lado, es un artefacto lógico . Es muy posible (y común) tener varias capas en el mismo ensamblaje.
En este caso, terminaremos teniendo la raíz de composición (capa) y la capa de presentación en el mismo proyecto de aplicación web (por lo tanto, en el mismo ensamblaje). Y aunque ese ensamblaje hace referencia al ensamblaje que contiene el DAL, la capa de presentación aún no hace referencia a la capa de acceso a datos . Esta es una gran distinción.
Por supuesto, cuando hacemos esto, perdemos la capacidad del compilador de verificar esta regla arquitectónica en el momento de la compilación, pero esto no debería ser un problema. El compilador no puede verificar la mayoría de las reglas arquitectónicas y siempre hay algo como el sentido común. Y si no hay sentido común en su equipo, siempre puede usar revisiones de código (que cada equipo debería hacer IMO siempre por cierto). También puede usar una herramienta como NDepend (que es comercial), que le ayuda a verificar sus reglas arquitectónicas. Cuando integra NDepend con su proceso de compilación, puede advertirle cuando alguien ingresó un código que viola dicha regla arquitectónica.
Puede leer una discusión más elaborada sobre cómo funciona la raíz de composición en el capítulo 4 de mi libro Inyección de dependencia, principios, prácticas, patrones .
fuente
Puede crear un proyecto separado llamado "DependencyResolver". En este proyecto, debe hacer referencia a todas sus bibliotecas.
Ahora, la capa de interfaz de usuario no necesita NHibernate / EF ni ninguna otra biblioteca que no sea relevante para la interfaz de usuario, excepto Castle Windsor como referencia.
Si desea ocultar Castle Windsor y DependencyResolver de su capa de interfaz de usuario, puede escribir un HttpModule que llame al material de registro de IoC.
Solo tengo un ejemplo para StructureMap:
DefaultControllerFactory no usa el contenedor IoC directamente, pero delega a los métodos del contenedor IoC.
El
GetController
delegado se configura en un registro de StructureMap (en Windsor debería ser un instalador).fuente
fuente