unity ioc injection ejemplo dependency container c# inversion-of-control unity-container

ioc - unity container c#



Mejores prácticas para el envase del COI (6)

Estoy usando el contenedor Unity IOC y me pregunto cuál es la mejor forma de acceder al contenedor para varias clases.

¿Debería cada clase tener un miembro IUnityContainer y luego pasar el contenedor por el constructor? ¿Debería haber una clase singleton con un contenedor IOC?

¿Qué tal el desarrollo de asp.net?

¿Podría alguien guiarme en la dirección correcta? Gracias.


Si todos sus objetos necesitan una referencia al contenedor, entonces debería revisar algunos de los códigos. Si bien es preferible a llamar nuevo en todas partes, aún dispersa la responsabilidad de construir sus gráficos de objetos a lo largo de su código. Con ese tipo de uso, me parece que se usa más como un ServiceLocator en lugar de un IoC Container.


puede registrar el contenedor en sí mismo y hacer que se lo inyecte como cualquier otra propiedad de dependencia, de esta manera:

IUnityContainer container = new UnityContainer(); container.RegisterInstance<IUnityContainer>(container);

las clases que necesitan acceder tendrán la siguiente propiedad:

private IUnityContainer unityContainer; [Dependency] public IUnityContainer UnityContainer { get { return unityContainer; } set { unityContainer = value; } }

por lo tanto, el contenedor se inyecta cada vez que se resuelve / construye una instancia de dicha clase.

Esto es más flexible ya que funciona para múltiples contenedores dentro de la misma aplicación, lo que no sería posible con el patrón singleton.


Otra opción sería usar el CommonServiceLocator , aunque puede ser una indirección sin sentido, puede usar ServiceLocator.Current como la instancia conocida por todas las clases



Coloque el contenedor de IOC en el nivel más alto / punto de entrada en el proceso y úselo para inyectar dependencias en todo lo que se encuentra debajo.


En mi humilde opinión, no es aconsejable inyectar todo el contenedor en una clase o tener un localizador de servicio de IoC estático.

Desea poder ver desde el constructor de una clase (vamos a llamarlo Foo) qué tipo de servicios / objetos está utilizando para realizar el trabajo. Esto mejora la claridad, la capacidad de prueba y la degubabilidad.

Digamos que Foo solo necesita el servicio de correo electrónico, pero transfiero el contenedor completo y en algún lugar del código se resuelve el servicio de correo electrónico desde el contenedor. En este caso, será muy difícil de seguir. En cambio, es mejor inyectar el servicio de correo electrónico directamente para indicar las dependencias de Foo más claras.

Si Foo necesita crear varias instancias del servicio de correo electrónico, es mejor crear e inyectar una EmailServiceFactory (a través del contenedor IoC), que creará las instancias necesarias sobre la marcha.

En este último caso, las dependencias de Foo siguen siendo lo más específicas posible, solo las que puede crear EmailServiceFactory. Si hubiera inyectado todo el contenedor, no estaría claro qué servicios proporcionados son las dependencias exactas de Foo.

Ahora, si luego deseo proporcionar diferentes instancias del servicio de correo electrónico, lo cambio dentro de EmailServiceFactory. Podría cambiar toda la fábrica también, si todos los servicios que crea deben intercambiarse (por ejemplo, durante la prueba).

Así que a costa de crear una clase extra (la fábrica), obtengo un código mucho más limpio y no tendré que preocuparme por los errores curiosos que pueden ocurrir cuando se utilizan estadísticas globales. Además, al suministrar simulacros para las pruebas, sé exactamente qué burlas necesita y no tengo que burlarme de los tipos de un contenedor completo.

Este enfoque también tiene la ventaja de que ahora, cuando se inicializa un módulo (solo se aplica a Prisma / Modularidad), no tiene que registrar todos los tipos de objetos que suministra con el contenedor IoC. En su lugar, puede registrar su ServiceFactory que luego suministra esos objetos.

Para que quede claro, la clase de inicialización del módulo (implementa IModule) debería recibir el contenedor IoC ancho de la aplicación en su constructor para suministrar servicios, que son consumidos por otros módulos, pero el contenedor no debería invadir las clases del módulo.

Finalmente, lo que tenemos aquí es otro buen ejemplo de cómo una capa adicional de indirección resuelve un problema.