utilizar unity qué que patron inyección inyeccion injection framework diseño desventajas dependency dependencias cuales control consideras casos apropiado c# dependency-injection unity-container ioc-container strategy-pattern

c# - unity - inyeccion de dependencias javascript



Patrón de estrategia e inyección de dependencia usando la unidad (1)

Finalmente me estoy mojando los pies con Dependency Injection (hace mucho tiempo); Comencé a jugar con Unity y me encontré con un problema con el patrón de estrategia. Puedo utilizar el contenedor para devolverme implementaciones específicas de una estrategia basada en un nombre, pero lo que no veo es cómo se supone que debo obtener la estrategia correcta en el contexto.
Vamos a ilustrar un ejemplo simple: el contexto es un automóvil, que tiene un IEngine (la estrategia), con 2 implementaciones, FastEngine y SlowEngine. El código se vería en esta línea:

public interface IEngine { double MaxSpeed { get; } } internal class FastEngine:IEngine { public double MaxSpeed { get { return 100d; } } } internal class SlowEngine:IEngine { public double MaxSpeed { get { return 10d; } } } public class Car { private IEngine engine; public double MaximumSpeed { get { return this.engine.MaxSpeed; } } public Car(IEngine engine) { this.engine = engine; } }

Mi problema es el siguiente: ¿cómo debo hacer para ejemplificar un automóvil rápido o un automóvil lento? Puedo usar el contenedor para proporcionarme cada implementación, y puedo establecer una implementación "predeterminada" para usar:

IUnityContainer container = new UnityContainer(); container.RegisterType<IEngine, FastEngine>(); container.RegisterType<IEngine, FastEngine>("Fast"); container.RegisterType<IEngine, SlowEngine>( "Slow" ); var car = container.Resolve<Car>(); Assert.AreEqual(100, car.MaximumSpeed);

pero lo que me gustaría es poder solicitar un automóvil con una implementación específica de la estrategia, algo así como

var car = container.Resolve<Car>(??? use "Fast" or "Slow ???);

¿Puedo usar el contenedor para hacer eso? ¿O debería escribir una fábrica que usa el contenedor? Cualquier orientación sería apreciada. ¡No estoy seguro de estar pensando en esto!


Un patrón común en DI es que en el tiempo de ejecución solo va a haber una implementación única de una abstracción dada. Eso simplemente hace la vida mucho más fácil, ya que no necesita lidiar con la ambigüedad como la que describe.

Sin embargo, a veces, debe variar una implementación en función del contexto, como el ejemplo que proporciona. Muchos Contenedores DI proporcionan formas en las que puede proporcionar un parámetro calificativo, pero eso significa que terminará acoplando estrechamente su código a un Contenedor DI específico.

Una solución mucho mejor sería introducir una fábrica abstracta que pueda proporcionarle lo que necesita. Algo como

public interface ICarFactory { Car Create(IEngine engine); }

Si necesita inyectar más Estrategias, quizás el patrón de diseño del Constructor encaje aún mejor.

En cualquier caso, el punto es que en lugar de registrar una gran cantidad de automóviles diferentes en el contenedor, en su lugar registraría una única implementación de ICarFactory.

En su código de cliente, usaría ICarFactory inyectado para crear una instancia de Car basada en un IE Engine particular.

var car = factory.Create(engine);