多实现类(如IService有ServiceA/ServiceB)的注入配置与获取
当一个接口有多个实现时,核心是**“注册时标记区分,获取时指定目标”**,常用两种方式:
1. 方式一:按“命名”注册(.NET 6+推荐,更直观)
注册时给每个实现起“名字”,获取时通过名字指定:
// 1. Program.cs 注册(给ServiceA/ServiceB分别加“标识”)
builder.Services.AddKeyedScoped<IService, ServiceA>("ServiceA"); // 键:"ServiceA"
builder.Services.AddKeyedScoped<IService, ServiceB>("ServiceB"); // 键:"ServiceB"
// 2. 在需要的地方获取(用[FromKeyedServices]指定键)
public class TestController : ControllerBase
{
// 注入ServiceA
private readonly IService _serviceA;
// 注入ServiceB
private readonly IService _serviceB;
    // 构造函数中通过“键”指定获取哪个实现
public TestController(
[FromKeyedServices("ServiceA")] IService serviceA,
[FromKeyedServices("ServiceB")] IService serviceB)
{
_serviceA = serviceA;
_serviceB = serviceB;
}
}
2. 方式二:注入“所有实现”(获取接口的所有实例集合)
如果需要用到该接口的全部实现(比如批量处理),可以直接注入IEnumerable<IService>:
// 1. Program.cs 注册(直接注册所有实现,无需额外标记)
builder.Services.AddScoped<IService, ServiceA>();
builder.Services.AddScoped<IService, ServiceB>();
// 2. 在需要的地方注入“所有实现的集合”
public class TestService
{
// 注入的是IService的所有实现(包含ServiceA和ServiceB)
private readonly IEnumerable<IService> _allServices;
    public TestService(IEnumerable<IService> allServices)
{
_allServices = allServices;
}
    // 使用时遍历集合,按需选择(比如按类型判断)
public void DoWork()
{
foreach (var service in _allServices)
{
if (service is ServiceA)
{
service.DoSomething(); // 调用ServiceA的逻辑
}
else if (service is ServiceB)
{
service.DoSomething(); // 调用ServiceB的逻辑
}
}
}
}
