我查看了这些概念,我想看看我是否正确理解了它们。主要是,我试图区分这三个概念。从谷歌搜索和其他结果来看,我看到了人们提供的很多关于它们的细节,但其中许多要么对我不完全清楚,要么矛盾,要么交换概念(IoC / DI)。我试图以更简单的方式定义它们,这对我来说更容易消化,我想看看它是否足够准确。
控制倒置
客户端类不直接实例化其依赖字段的实现类,因为它依赖于其他一些外部类/源来提供它们。在大多数情况下,字段是父类或接口,它具有一个或多个子类,将作为实现提供。
依赖注入
客户端类接收其依赖字段的实现类,无论是通过构造函数,setter还是其他,以及此实现 是一个全新的对象实例。供应类可能使用另一种模式,例如工厂,以确定传递给客户端的实现(或者甚至可以直接实例化新实例并将其传递到客户端的构造函数中)。
服务定位器
客户端类是调用服务定位器以提供其依赖字段的类。返回的实现是一个对象实例,可以与依赖于相同依赖关系的任何其他客户端类共享。
我尝试了一个非常简单的例子:
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是处理供应方概念的两种可能方式。
感谢。如果我错误地使用了任何条款,我也会道歉。
编辑:感谢您的回复!
答案 0 :(得分:2)
是的,你是对的。
SL通常在框架内部使用,以便能够找到所有服务。从开发人员的角度来看,他们只是使用依赖注入,因为框架隐藏了服务位置。一个典型的例子是ASP.NET MVC,您可以在控制器中使用DI。 ASP.NET通过DependencyResolver
类在内部使用服务位置,以允许您使用DI。
对于业务线应用程序,DI优先于SL,因为SL隐藏了依赖关系,这反过来又使得维护应用程序变得更加困难。
答案 1 :(得分: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());
}