使用IoC容器的OOD - 如何构建依赖对象?

Val*_*zub 5 c# oop dependency-injection inversion-of-control autofac

我正在尝试使用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();

}
Run Code Online (Sandbox Code Playgroud)

我在想这里应该采用什么方法.我们可以给构造函数留下3个参数,但是如果我们使用autofac构建应用程序(例如),很可能除了从某些容器实例中解析类型之外很少使用它

    Processor proc = new Processor(
 container.Resolve<IService1>(),
 container.Resolve<IService2>(),
 container.Resolve<IService3>());
Run Code Online (Sandbox Code Playgroud)

所以当我们依赖容器中的多种类型时,我想也许方法2更好.无论如何,我们将不得不在某处添加autofac的引用,所以任何理由现在都不要这样做?

Autofac还提供委托工厂方法方法

http://code.google.com/p/autofac/wiki/DelegateFactories

var processorFactory = container.Resolve<Processor.Factory>();
Processor processor = processorFactory.Invoke();
Run Code Online (Sandbox Code Playgroud)

所以我们也有方法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;
        }
}
Run Code Online (Sandbox Code Playgroud)

现在我们创造了

//approach 4
public Processor(ServiceLocatorObject servicesToUse)
{
    m_Services = servicesToUse;
}
Run Code Online (Sandbox Code Playgroud)

现在我们已经将类与服务实现分离,并清楚它需要什么样的实际依赖项(如果我们假设所有服务都需要传递对象),因为我们没有传递一个可以包含100个实现的容器.如果在我们的应用程序中的某个另一个类中可能需要该服务组合,那么该对象甚至可以被重用.所以我们使用构造函数DI而不是ServiceLocator模式.接口是清晰的,没有依赖的重载,新类可能是一个很好的重用候选者.

你对这个怎么说?

Jef*_*eff 6

现在,服务位置模式通常被认为是反模式(使用container.Resolve和注入容器).

在我自己努力解决这个概念并试图决定我是喜欢它还是讨厌它之后,我逐渐认识到我同意服务位置是一种反模式 - 因为它模糊了存在的相互依赖性,这是一个核心OOP的概念.

请阅读:http: //blog.ploeh.dk/2010/02/03/ServiceLocatorIsAnAntiPattern.aspx

实际上,我认为在选项1中,Process CLEARLY表示它对列出的每个服务的依赖关系是构造函数中的参数.它使依赖性非常明显......而且我认为它有助于促进良好的设计.

只是说处理器需要一个IContainer并没有告诉我们太多...因此你需要仔细看看以确定相互依赖性.


Mar*_*ann 6

JeffN825给出的答案是正确的,但我想补充一点,你永远不会使用像这样的容器创建一个新的Processor实例:

Processor proc = new Processor(
    container.Resolve<IService1>(),
    container.Resolve<IService2>(),
    container.Resolve<IService3>());
Run Code Online (Sandbox Code Playgroud)

相反,您可以让容器自动连接依赖项并一次解决:

Processor proc = container.Resolve<Processor>();
Run Code Online (Sandbox Code Playgroud)