【发布时间】:2019-08-27 22:05:05
【问题描述】:
我想知道为什么不显式使用 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 吗?无论如何,同样的事情不会在后台发生吗?
【问题讨论】:
-
...无论我们在哪里调用构造函数... ...那你为什么需要 DI?
-
使用第二种方法,您可以将整个应用程序依赖项注入到您打算使用它们的任何位置,而不管您实际需要哪些依赖项。这会增加对象创建时间。
-
@MartBroekkamp 如果您在单个控制器中有 10 多个依赖项 - 这是代码味道,告诉您您的控制器做得太多。我会把它分成更小的控制器。或者聚合外观背后的依赖关系。此外,创建服务实例应该既便宜又容易,即构造函数除了分配依赖项之外不应该做任何事情。
-
@mjwills OP,据我所知,服务定位器模式对于处理生命周期没有任何内在意义。正如您已经指出的那样,这会很痛苦。
-
@mjwills 点了,我尝试为 IServiceProvider 方式编写单元测试,并很快意识到这将是多么痛苦。
标签: c# dependency-injection .net-core