为什么不注入IServiceProvider而不是注入每个依赖关系?

时间:2019-08-27 12:29:38

标签: c# dependency-injection .net-core

我想知道为什么不通过单独注入每个依赖项来明确使用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吗?反正是在后台发生同一件事?

2 个答案:

答案 0 :(得分:2)

有几个原因。 使用依赖项注入时,您将为DI容器负责为您准备依赖项。这些类不必关心如何创建依赖项。如果切换到其他DI库,则必须在所有类中更改构造函数。

另一个小问题是,您必须在每个单元测试中为服务容器创建一个模拟,这不是一个大问题,但肯定会令人讨厌。

最后,当您必须将依赖项传递给嵌套类时,您的代码将变得非常奇怪,更不用说您希望继承了。

答案 1 :(得分:1)

这称为服务定位器模式-> https://en.wikipedia.org/wiki/Service_locator_pattern

它有一些优点和缺点(在文章中有介绍),但是它被广泛认为是一种反模式。


您声明自己是在自己调用构造函数(例如,我猜是在new SomeService(...)中,这表明未使用DI(或仅部分使用了DI)。