构造函数中的循环依赖注入

时间:2019-08-07 17:14:07

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

鉴于这种情况:

public class A : IA
{
    private IB _ib { get; }
    public A(IB ib)
    {
        _ib = ib;
    }
}

public class B : IB
{
    private IA _ia { get; }
    public B(IA ia)
    {
        _ia = ia;
    }
}

并且在Startup.cs处都注册为Singleton

为什么这不属于循环依赖?

1 个答案:

答案 0 :(得分:2)

如果如您的注释中所示,依赖项的注册方式如下:

services.AddSingleton<IA, A>();
services.AddSingleton<IB, B>();

...解析IAIB都会失败,并发生异常。这可以通过单元测试来证明。

[TestMethod]
public void TestCircularDependency()
{
    var services = new ServiceCollection();
    services.AddSingleton<IA, A>();
    services.AddSingleton<IB, B>();
    var provider = services.BuildServiceProvider();
    var a = provider.GetService<IA>();
    var b = provider.GetService<IB>();
}

任何一种解决方法都失败,但有一个例外:

  

System.InvalidOperationException:检测到类型为'UnitTestProject1.IB'的服务的循环依赖关系。

要使 not 失败是不可能的。在我们的代码中经常发生似乎不可能的事情,但是实际上在每种情况下,原因都是一个不正确的假设。

您还提到它在一种环境中有效,但在另一种环境中无效。假设(我已经做了很多次)是在两个环境中都运行相同的代码,但在这种情况下不是。

在这种情况下,解决IA的唯一方法是,如果存在IA的另一种实现或IB的另一种实现(或者非常不可能-null是作为依赖项注入一个或另一个。)


这种问题很有趣,因为当我们看到似乎不可能的事情时,我们的倾向(至少是我的倾向)常常盯着它,想知道不可能的事情是怎么发生的。一旦我们确定我们正在思考的事情是不可能的,就表明我们应该开始质疑其他所有导致这一结论的假设。其中之一必须是假的。