我正在尝试使用IoC,DI和OOD来获得更好的可测试性和更松散的耦合。
因此,当我们设计大量使用IoC和DI的类时,我们可以使用具有多个依赖关系的类,例如
class Processor
{
private IService1 m_Service1;
private IService2 m_Service2;
private IService3 m_Service3;
//approach 1
public Processor(IService1 service1, IService2 service2, IService3 service3)
{
m_Service1 = service1;
m_Service2 = service2;
m_Service3 = service3;
}
//approach 2
public Processor(IContainer container)
{
m_Service1 = container.Resolve<IService1>();
m_Service2 = container.Resolve<IService2>();
m_Service3 = container.Resolve<IService3>();
}
//approach 3
public delegate Processor Factory();
}
我在想这里应该采用什么方法。我们可以给构造函数留下3个参数,但是如果我们使用autofac构建应用程序(例如),很可能除了从某个容器实例中解析类型之外很少使用它,比如
Processor proc = new Processor(
container.Resolve<IService1>(),
container.Resolve<IService2>(),
container.Resolve<IService3>());
所以当我们依赖容器中的多种类型时,我想也许方法2更好。无论如何,我们必须在某个地方添加autofac的引用,所以现在有任何理由不这样做吗?
Autofac还提供委托工厂方法方法
http://code.google.com/p/autofac/wiki/DelegateFactories
var processorFactory = container.Resolve<Processor.Factory>();
Processor processor = processorFactory.Invoke();
所以我们也接近3 - 我们不会使用构造函数来创建我们的类实例,而是我们将从容器中调用已解析的委托,它将解决我们的依赖关系。
由于我对IoC很新,很难说我们何时应该使用1,2,3。它们各有利弊。
我认为一般来说,如果类有1依赖,我们可能总是使用方法1 ..除此之外,我真的不确定选择什么以及什么时候。
更新我已阅读有关服务定位器反模式但我已提出第4(或真正的第3种方法)
它接近ServiceLocator,除了它没有,我们传递一个看起来像这样的对象
public class ServiceLocatorObject
{
private IService1 m_Service1;
private IService2 m_Service2;
private IService3 m_Service3;
public IService1 Service1 {get {return m_Service1;}}
public IService2 Service2 {get {return m_Service2;}}
public IService3 Service3 {get {return m_Service3;}}
public ServiceLocatorObject(IService1 service1, IService2 service2, IService3 service3)
{
m_Service1 = service1;
m_Service2 = service2;
m_Service3 = service3;
}
}
现在我们创建
//approach 4
public Processor(ServiceLocatorObject servicesToUse)
{
m_Services = servicesToUse;
}
现在我们已经将我们的类与服务实现分离,并清楚它需要什么样的真实依赖项(如果我们假设所有服务都需要传递对象),因为我们没有传递一个可以包含100个实现的容器。如果在我们的应用程序中的某个另一个类中可能需要该3个服务组合,那么该对象甚至可以被重用。所以我们使用构造函数DI而不是ServiceLocator模式。接口是清晰的,没有重载依赖,新类可能是一个很好的重用候选者。
你对这个怎么说?
答案 0 :(得分:6)
服务地点模式现在通常被认为是反模式(使用container.Resolve和注入容器)。
在我自己努力解决这个概念并试图决定我是喜欢它还是讨厌它之后,我逐渐认识到我同意服务位置是一种反模式 - 因为它模糊了存在的相互依赖关系是OOP的核心概念。
请阅读: http://blog.ploeh.dk/2010/02/03/ServiceLocatorIsAnAntiPattern.aspx
实际上,我认为在选项1中,Process CLEARLY表示它对列出的每个服务的依赖关系是构造函数中的参数。它使依赖性非常明显......而且我认为它有助于促进良好的设计。
只是说处理器需要一个IContainer并没有告诉我们什么......因此你需要仔细看看以确定相互依赖性。
答案 1 :(得分:6)
JeffN825给出的答案是正确的,但我想补充一点,你永远不会使用像这样的容器创建一个新的Processor实例:
Processor proc = new Processor(
container.Resolve<IService1>(),
container.Resolve<IService2>(),
container.Resolve<IService3>());
相反,您可以让容器自动连接依赖项和resolve it one go:
Processor proc = container.Resolve<Processor>();
答案 2 :(得分:0)
这不是关于依赖的数量,也不是每个类的决定。方法2引入了一个新的依赖项,但是如果你想依赖一个IoC容器,那么这是一个很好的方法。方法3就像第二种方法,但是让你今后在工厂做一些事情。方法1最简单,不依赖任何东西,应该用于通常不通过IoC容器管理的依赖项。