.NET Core控制台DI:多接口实现无法获取指定实例报错
问题根源
当你将多个实现类注册为同一个接口IMainAction的Transient服务时,.NET DI容器的默认行为是:每次请求IMainAction实例时,都会返回最后注册的那个实现类。
比如你的注册代码如果是这样:
builder.Services.AddTransient<IMainAction, CityStoreClass>(); builder.Services.AddTransient<IMainAction, ProvinceService>();
此时容器中IMainAction的"默认"实现是ProvinceService——不管你注入多少次IMainAction,拿到的都是ProvinceService实例。这就是你尝试把它强制转换为CityStoreClass时抛出类型转换异常的原因。
解决方案
根据你的需求,有几种可行的解决方式:
1. 使用带键(Keyed)的服务(.NET 6+支持)
通过给不同的实现类标记唯一键,注入时指定键来获取对应实例,避免依赖类型强制转换:
注册服务
builder.Services.AddKeyedTransient<IMainAction, CityStoreClass>("city"); builder.Services.AddKeyedTransient<IMainAction, ProvinceService>("province");
在App类中注入
public class App { private readonly IMainAction _cityService; private readonly IMainAction _provinceService; // 使用[FromKeyedServices]指定要注入的实例键 public App([FromKeyedServices("city")] IMainAction cityService, [FromKeyedServices("province")] IMainAction provinceService) { _cityService = cityService; _provinceService = provinceService; } public void Run() { _cityService.Run(); // 直接调用,无需强制转换 _provinceService.Run(); } }
2. 注入IEnumerable<IMainAction>并筛选实例
如果你不想用键服务,可以注入所有IMainAction的实例集合,然后通过类型筛选出需要的实现:
注册服务(保持你原来的注册方式不变)
builder.Services.AddTransient<IMainAction, CityStoreClass>(); builder.Services.AddTransient<IMainAction, ProvinceService>();
在App类中筛选实例
public class App { private readonly CityStoreClass _cityService; private readonly ProvinceService _provinceService; public App(IEnumerable<IMainAction> allMainActions) { _cityService = allMainActions.OfType<CityStoreClass>().FirstOrDefault() ?? throw new InvalidOperationException("未找到CityStoreClass的DI实例"); _provinceService = allMainActions.OfType<ProvinceService>().FirstOrDefault() ?? throw new InvalidOperationException("未找到ProvinceService的DI实例"); } public void Run() { _cityService.Run(); _provinceService.Run(); } }
3. 直接注册并注入具体实现类
如果你的业务逻辑确实需要直接依赖具体类而非接口,可以跳过接口注册,直接注册实现类:
注册服务
builder.Services.AddTransient<CityStoreClass>(); builder.Services.AddTransient<ProvinceService>();
在App类中注入
public class App { private readonly CityStoreClass _cityService; private readonly ProvinceService _provinceService; // 直接注入具体类型,完全避免接口映射的歧义 public App(CityStoreClass cityService, ProvinceService provinceService) { _cityService = cityService; _provinceService = provinceService; } public void Run() { _cityService.Run(); _provinceService.Run(); } }
内容的提问来源于stack exchange,提问作者Cyrus the Great
相关产品推荐
相关产品推荐

