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

发布于 2024-08-10 03:40:57 字数 1395 浏览 8 评论 0原文

我终于开始接触依赖注入了(早就该这么做了);我开始使用 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;
    }
}

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

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);

但我希望能够请求一辆具有特定策略实现的汽车 - 例如

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

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

I am finally getting my feet wet with Dependency Injection (long overdue); I got started playing with Unity and run into an issue with the strategy pattern. I can use the container to return to me specific implementations of a strategy based on a name, but what I don't see is how I am supposed to get the right strategy in the context.
Let's illustrate on a simple example: the context is a car, which has an IEngine (the strategy), with 2 implementations, FastEngine and SlowEngine. The code would look along these lines:

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;
    }
}

My problem is the following: how should I go about instantiating a fast car or a slow car? I can use the container to provide me with each implementation, and I can set a "default" implementation to use:

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);

but what I would like is to be able to request a car with a specific implementation of the strategy - something like

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

Can I use the container to do that? Or should I write a Factory which uses the container? Any guidance would be appreciated - I am not sure I am thinking right about this!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

吖咩 2024-08-17 03:40:57

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

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

更好的解决方案是引入一个可以提供您所需的 Abstract Factory 。 。

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

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

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

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

var car = factory.Create(engine);

A common pattern in DI is that at run-time there's only going to be a single implementation of a given abstraction. That just makes life a whole lot easier, as you don't need to deal with the ambiguity such as the one you describe.

However, sometimes, you need to vary an implementation based on context, such as the example you give. Many DI Containers provide ways where you can provide a qualifying parameter, but that means that you will end up tightly coupling your code to a specific DI Container.

A much better solution would be to introduct an Abstract Factory that can provide what you need. Something like

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

If you need to inject more Strategies, perhaps the Builder design pattern might fit even better.

In any case, the point is that instead of registering a lot of different Cars in the container, you would instead register a single ICarFactory implementation.

In your client code, you would use the injected ICarFactory to create a Car instance based on a particular IEngine.

var car = factory.Create(engine);
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文