23

我终于使我的脚湿依赖注入(长期过期);我开始玩Unity,并遇到了一个与战略模式有关的问题。我可以使用容器向我返回基于名称的策略的特定实现,但我没有看到的是我如何在上下文中获得正确的策略。
让我们举个简单的例子来说明:上下文是一辆汽车,它有一个IEngine(策略),有2个实现,FastEngine和SlowEngine。该代码将沿着这些路线看:使用Unity的策略模式和依赖注入

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

我可以使用容器来做到这一点吗?或者我应该写一个使用容器的工厂?任何指导将不胜感激 - 我不知道我在想这个!

回答

26

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

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

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

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

如果需要注入更多的战略东西,也许是Builder设计模式可能适合,甚至更好。

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

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

var car = factory.Create(engine); 
+0

谢谢,有见地的答案。我使用战略模式,在运行时多种策略交换,很多;默认情况下,我会做你所描述的(工厂或生成器),但我看到很多策略模式和DI关联,虽然这可能有所帮助。从你所说的话来看,一个容器似乎只有一点帮助。 – Mathias 2009-11-10 20:43:14

+0

我仍然认为集装箱是非常有帮助的。在这些情况下,他们只会注入工厂而不是策略,但我想你仍然可以选择使用容器来实现工厂... – 2009-11-10 21:02:15

+4

哦,我想我明白你的意思了;而不是退回合适的车辆,根据发动机返回正确的工厂。在任何情况下,您的评论re:用于为抽象提供单个实现的容器都非常有用;它与我看到的以配置为导向的示例一致。在该框架中,您可以拥有策略模式,但特定的部署只会配置一个实施。 – Mathias 2009-11-11 06:14:11