0

我查阅了这些概念,我想看看我是否正确理解了它们。主要是,我试图区分这三个概念。从这里的谷歌搜索和其他结果中,我看到了人们提供的很多关于它们的细节,但其中许多对我来说并不完全清楚,相互矛盾或互换概念(IoC/DI)。我正在尝试以一种更简单的方式来定义它们,这对我来说更容易消化,我想看看它是否足够准确。

控制反转

客户端类不直接实例化其依赖字段的实现类,因为它依赖于其他一些外部类/源来提供它们。在大多数情况下,这些字段是一个父类或接口,它具有一个或多个子类,这些子类将作为实现提供。

依赖注入

客户端类接收其依赖字段的实现类,无论是通过构造函数、设置器还是其他方式,并且此实现是一个全新的对象实例。提供类可能使用另一种模式,例如工厂,以确定将什么实现传递给客户端(或者它甚至可能直接实例化一个新实例并将其传递给客户端的构造函数)。

服务定位器

客户端类是调用服务定位器以提供其依赖字段的类。返回的实现是一个对象实例,可以与依赖相同依赖项的任何其他客户端类共享。

我尝试一个非常简单的例子:

迪:

public interface IX {

}

public class X : IX {

}

public class A {
    IX depField;

    public A(IX depField) {
        this.depField = depField;
    }   
}

public void main() {
    A myClass = new A(new X());
}

SL:

public interface IX {

}

public class X : IX {

}

public class A {
    IX depField = serviceLocatorObj.GetService<IX>(); 
    //where IX is mapped to X in the service locator class
}

public void main() {
    A myClass = new A();
}

IoC 是接收方的概念,而 DI 和 SL 是处理供应方概念的两种可能方式。

谢谢。如果我错误地使用了任何术语,我也深表歉意。

编辑:感谢您的回复!

4

2 回答 2

2

是的,你是对的。

SL 通常在框架内使用,以便能够定位所有服务。从开发人员的角度来看,他们只是在使用依赖注入,因为框架隐藏了服务位置。一个典型的例子是 ASP.NET MVC,你可以在你的控制器中使用 DI。ASP.NET 通过DependencyResolver类在内部使用服务位置以允许您使用 DI。

对于业务线应用程序,DI 优于 SL,因为 SL 隐藏了依赖关系,这反过来又使维护应用程序变得更加困难。

于 2013-05-07T06:37:23.633 回答
1

服务位置也使单元测试变得更加困难,因为它们通常是静态类,这剥夺了模拟它们的能力。

考虑这些构造函数注入和服务定位的例子。

服务地点:

 public class Foo
    {
        public void DoSomething()
        {
            var provider = ServiceLocator.GetInstance<IProvider>();

            provider.DoIt();
        }
    }

构造函数注入:

 public class Foo
    {
        private readonly IProvider _provider;

        public Foo(IProvider provider)
        {
            _provider = provider;
        }

        public void DoSomething()
        {
            _provider.DoIt();
        }
    }

在构造函数中传递一个模拟/伪造的 IProvider 很简单,而在服务定位器示例中,这变得更加困难,因为您首先需要抽象 ServiceLocator 类。

    [Test]
    public void DoSomething_ShouldCallDoIt()
    {
        var mockProvider = new Mock<IProvider>();

        var foo = new Foo(mockProvider);

        foo.DoSomething();

        mockProvider.Verify(x => x.DoIt());
    }
于 2013-09-26T09:15:52.123 回答