为什么 .NET Core DI 更喜欢接受 IEnumerable<T> 的构造函数而不是无参数构造函数?
Why .NET Core DI prefers constructor accepting IEnumerable<T> over parameterless one?
我有一个简单的服务接口:
public interface ICustomService
{
bool ConstructedWithNoParameters { get; }
}
实现同样简单:
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; }
}
请注意,根据调用的构造函数,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();
}
因为我没有指定应该如何构造实现,所以我希望调用无参数构造函数来初始化 CustomService
的新实例。但事实并非如此。上面的测试方法在以 ConstructedWithNoParameters
为 false
结束断言时失败。在我看来,DI 解析器更喜欢接受 IEnumerable<int>
的其他构造函数而不是无参数构造函数。如果我只保留无参数构造函数可用,则测试通过。
我正在使用 .NET Core 2.2 和 XUnit 2.4.0 进行测试。
问题
为什么 DI 解析器更喜欢接受 IEnumerable<T>
而不是无参数的构造函数?
DI被设计成贪婪的,选择它能填充的参数最多的构造函数。可枚举参数仍然可以由 DI 使用空数组 构造,因此 DI 仍然可以进行重载。我相信这就是幕后发生的事情。
我有一个简单的服务接口:
public interface ICustomService
{
bool ConstructedWithNoParameters { get; }
}
实现同样简单:
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; }
}
请注意,根据调用的构造函数,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();
}
因为我没有指定应该如何构造实现,所以我希望调用无参数构造函数来初始化 CustomService
的新实例。但事实并非如此。上面的测试方法在以 ConstructedWithNoParameters
为 false
结束断言时失败。在我看来,DI 解析器更喜欢接受 IEnumerable<int>
的其他构造函数而不是无参数构造函数。如果我只保留无参数构造函数可用,则测试通过。
我正在使用 .NET Core 2.2 和 XUnit 2.4.0 进行测试。
问题
为什么 DI 解析器更喜欢接受 IEnumerable<T>
而不是无参数的构造函数?
DI被设计成贪婪的,选择它能填充的参数最多的构造函数。可枚举参数仍然可以由 DI 使用空数组 构造,因此 DI 仍然可以进行重载。我相信这就是幕后发生的事情。