我想知道为什么不通过单独注入每个依赖项来明确使用IServiceProvider来解决依赖项。换句话说,为什么要使用这种方法:
public class A
{
private B _b;
private C _c;
private D _d;
private E _e;
public A(B b, C c, D d, E e)
{
_b = b;
_c = c;
_d = d;
_e = e;
}
}
不是这个:
public class A
{
private B _b;
private C _c;
private D _d;
private E _e;
public A(IServiceProvider sp)
{
_b = (b) sp.GetService(typeof(b));
_c = (c) sp.GetService(typeof(c));
_d = (d) sp.GetService(typeof(d));
_e = (e) sp.GetService(typeof(e));
}
}
请注意,我可能不会为所有类型调用GetService
,其中某些类型实际上是可选的(即有时使用,有时不使用)。
第二种方法的优点是,如果A的依赖项发生了变化,我们不需要在调用A的构造函数的每个位置进行更改,而不必无论我们在哪里调用构造函数,所有依赖项都已经可用。
在以下文章中,MS似乎对此建议不推荐:https://docs.microsoft.com/en-us/aspnet/core/fundamentals/dependency-injection?view=aspnetcore-2.2#recommendations 他们提到要避免使用服务定位器模式代替DI,但是我们不是在这里仍然使用DI吗?反正是在后台发生同一件事?
答案 0 :(得分:2)
有几个原因。 使用依赖项注入时,您将为DI容器负责为您准备依赖项。这些类不必关心如何创建依赖项。如果切换到其他DI库,则必须在所有类中更改构造函数。
另一个小问题是,您必须在每个单元测试中为服务容器创建一个模拟,这不是一个大问题,但肯定会令人讨厌。
最后,当您必须将依赖项传递给嵌套类时,您的代码将变得非常奇怪,更不用说您希望继承了。
答案 1 :(得分:1)
这称为服务定位器模式-> https://en.wikipedia.org/wiki/Service_locator_pattern
它有一些优点和缺点(在文章中有介绍),但是它被广泛认为是一种反模式。
您声明自己是在自己调用构造函数(例如,我猜是在new SomeService(...)
中,这表明未使用DI(或仅部分使用了DI)。