使用Unity的策略模式和依赖注入

Mat*_*ias 24 c# dependency-injection ioc-container unity-container strategy-pattern

我终于忍受了Dependency Injection(早就应该); 我开始玩Unity并遇到战略模式的问题.我可以使用容器向我返回基于名称的策略的特定实现,但我没有看到我应该如何在上下文中获得正确的策略.
让我们举一个简单的例子说明:上下文是一辆汽车,它有一个IEngine(策略),有2个实现,FastEngine和SlowEngine.代码将沿着这些方向看:

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;
    }
}
Run Code Online (Sandbox Code Playgroud)

我的问题如下:我应该如何实例化快车或慢车?我可以使用容器为我提供每个实现,我可以设置一个"默认"实现来使用:

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);
Run Code Online (Sandbox Code Playgroud)

但我想要的是能够要求一辆具有特定战略实施的汽车 - 比如

var car = container.Resolve<Car>(??? use "Fast" or "Slow ???);
Run Code Online (Sandbox Code Playgroud)

我可以用容器来做吗?或者我应该写一个使用容器的工厂?任何指导将不胜感激 - 我不确定我是否正确的想法!

Mar*_*ann 27

DI中的一个常见模式是,在运行时,只有一个给定抽象的实现.这只会让生活变得更加容易,因为你不需要处理你所描述的模糊性.

但是,有时,您需要根据上下文更改实现,例如您提供的示例.许多DI容器提供了可以提供限定参数的方法,但这意味着您最终会将代码紧密耦合到特定的DI容器.

一个更好的解决方案是引入一个可以提供所需内容的抽象工厂.就像是

public interface ICarFactory
{
    Car Create(IEngine engine);
}
Run Code Online (Sandbox Code Playgroud)

如果您需要注入更多策略,那么Builder设计模式可能更适合.

无论如何,重点是不是在容器中注册很多不同的汽车,而是注册一个ICarFactory实现.

在您的客户端代码中,您将使用注入的ICarFactory基于特定的IEngine创建Car实例.

var car = factory.Create(engine);
Run Code Online (Sandbox Code Playgroud)

  • 哦,我想我明白了你的意思; 而不是返回正确的汽车,返回基于发动机的正确的工厂.在任何情况下,您的评论re:用于为抽象提供单个实现的容器非常有用; 它与我看到的示例一致,它们是面向配置的.在该框架中,您可以拥有策略模式,但特定部署将只配置一个实现. (4认同)