为什么.NET Core DI首选构造函数而不是无参数构造函数接受IEnumerable <T>?

Pro*_*log 3 c# ienumerable dependency-injection .net-core

我有一个简单的服务界面:

public interface ICustomService
{
    bool ConstructedWithNoParameters { get; }
}
Run Code Online (Sandbox Code Playgroud)

同样简单的实现:

public class CustomService : ICustomService
{
    private readonly IEnumerable<int> _items;

    public CustomService()
    {
        _items = Enumerable.Empty<int>();

        ConstructedWithNoParameters = true;
    }

    public CustomService(IEnumerable<int> items)
    {
        _items = items ?? throw new ArgumentNullException(nameof(items));
    }

    public bool ConstructedWithNoParameters { get; }
}
Run Code Online (Sandbox Code Playgroud)

请注意,根据调用哪个构造函数,将ConstructedWithNoParameters设置为true

这是一个简单的测试场景来进行测试:

[Fact]
public void Test1()
{
    // Assert
    var serviceProvider = new ServiceCollection()
        .AddTransient<ICustomService, CustomService>()
        .BuildServiceProvider();

    // Act
    var customService = serviceProvider.GetRequiredService<ICustomService<int>>();

    // Arrange
    customService.ConstructedWithNoParameters.Should().BeTrue();
}
Run Code Online (Sandbox Code Playgroud)

由于我没有指定实现的构造方式,因此我期望调用无参数构造函数来初始化的新实例CustomService。但是,事实并非如此。上述试验方法失败在结尾断言ConstructedWithNoParametersfalse。在我看来,DI解析器更喜欢其他构造函数而IEnumerable<int>不是无参数的构造函数。如果我仅保留无参数构造函数可用,则测试通过。

我正在使用.NET Core 2.2和XUnit 2.4.0进行测试。

为什么DI解析器更喜欢构造函数接受而IEnumerable<T>不是无参数?

aja*_*987 8

DI被设计为贪婪的,并选择可以填充的最多参数的构造函数。DI仍然可以由带有空数组的DI构造可枚举的参数,因此DI仍可以进行该重载。我相信那是在幕后发生的事情。

  • 源代码确认了这一点。 (3认同)