dependency-injection - control - dependency injection container
¿Por qué no pasar el contenedor de IoC? (4)
En esta página de "Mejores prácticas" de AutoFac ( http://code.google.com/p/autofac/wiki/BestPractices ), dicen:
No pase el contenedor. Darle acceso a los componentes al contenedor, almacenarlo en una propiedad estática pública o hacer que funciones como Resolve () estén disponibles en una clase ''IoC'' global anula el propósito de usar la inyección de dependencia. Tales diseños tienen más en común con el patrón de Localizador de Servicio. Si los componentes tienen una dependencia en el contenedor, observe cómo utilizan el contenedor para recuperar servicios y agregue esos servicios a los argumentos de constructor del componente (dependencia inyectada) en su lugar.
Entonces, ¿cuál sería una mejor manera de tener un componente "dinámicamente" instanciar otro? Su segundo párrafo no cubre el caso en el que el componente que "debe" ser creado dependerá del estado del sistema. O cuando el componente A necesita crear X número de componente B.
Autofac en realidad tiene alguna funcionalidad especial para este escenario exacto, los detalles se encuentran en la wiki aquí: http://code.google.com/p/autofac/wiki/DelegateFactories .
En esencia, si A necesita crear varias instancias de B, A puede tomar una dependencia en Func <B> y Autofac generará una implementación que devuelve nuevas Bs del contenedor.
Las otras sugerencias anteriores son, por supuesto, válidas. El enfoque de Autofac tiene un par de diferencias:
- Evita la necesidad de un gran número de interfaces de fábrica.
- B (el producto de la fábrica) todavía puede tener dependencias inyectadas por el contenedor
¡Espero que esto ayude!
Mella
Los patrones del localizador de servicios son más difíciles de probar y ciertamente es más difícil controlar las dependencias, lo que puede llevar a un mayor acoplamiento en su sistema del que realmente desea.
Si realmente quieres algo como una instanciación perezosa, puedes optar por el estilo del Localizador de servicios (no te mata de inmediato y si te adhieres a la interfaz del contenedor no es muy difícil probarlo con un marco de burla). Tenga en cuenta, sin embargo, que la creación de instancias de una clase que no hace mucho (o nada) en el constructor es inmensamente barata.
El contenedor que he llegado a conocer (no autofac hasta ahora) le permitirá modificar qué dependencias se deben inyectar en qué instancia, dependiendo del estado del sistema, de modo que incluso esas decisiones puedan ser externalizadas en la configuración del contenedor.
Esto puede proporcionarle mucha flexibilidad sin tener que recurrir a implementar la interacción con el contenedor en función de algún estado al que acceda en las dependencias que consumen la instancia.
Para abstraer la creación de instancias de otro componente, puede usar el patrón de Fábrica:
public interface IComponentBFactory
{
IComponentB CreateComponentB();
}
public class ComponentA : IComponentA
{
private IComponentBFactory _componentBFactory;
public ComponentA(IComponentBFactory componentBFactory)
{
_componentBFactory = componentBFactory;
}
public void Foo()
{
var componentB = _componentBFactory.CreateComponentB();
...
}
}
Entonces la implementación puede ser registrada con el contenedor IoC.
Un contenedor es una forma de ensamblar un gráfico de objetos, pero ciertamente no es la única. Es un detalle de implementación. Mantener los objetos libres de este conocimiento los desvincula de las preocupaciones de infraestructura. También les impide tener que saber qué versión de una dependencia resolver.
Una IoC asume la responsabilidad de determinar qué versión de una dependencia debe usar un objeto determinado. Esto es útil para hacer cosas como crear cadenas de objetos que implementan una interfaz, así como tener una dependencia de esa interfaz (similar a una cadena de comando o patrón decorador).
Al pasar su contenedor, está poniendo la responsabilidad en el objeto individual para obtener la dependencia adecuada, por lo que debe saber cómo hacerlo. Con el uso típico de IoC, el objeto solo necesita declarar que tiene una dependencia, no pensar en seleccionar entre múltiples implementaciones disponibles de esa dependencia.