开放泛型接口对应封闭实现类的依赖注入注册方法
泛型服务依赖注入注册方案
原有写法错误原因
你之前三种注册方式报错的核心原因分两类:
- 开放泛型注册规则不匹配
services.AddTransient(typeof(IViewModelService<>), typeof(HomeViewModelService));typeof(IViewModelService<>)是未指定类型参数的开放泛型服务类型,这种注册方式要求第二个参数传入的实现类型也必须是开放泛型。但你的HomeViewModelService是固定绑定了HomeViewModel类型参数的封闭实现类,本身不是开放泛型,不符合开放泛型注册的要求。 - 泛型参数传值错误
services.AddTransient(typeof(IViewModelService<HomeViewModelService>), typeof(HomeViewModelService)); services.AddScoped<IViewModelService<HomeViewModelService>, HomeViewModelService>();HomeViewModelService实现的接口契约是IViewModelService<HomeViewModel>,不是IViewModelService<HomeViewModelService>——你把接口要求的视图模型类型参数,错传成了服务实现类本身的类型,自然不存在类型转换关系,容器无法完成类型映射。
正确注册代码
你的场景属于「泛型接口的封闭类型实现」,注册时直接把接口的泛型参数指定为对应绑定的视图模型类型即可,生命周期可以根据业务需求选择Scoped/Transient/Singleton:
// 泛型写法 services.AddScoped<IViewModelService<HomeViewModel>, HomeViewModelService>(); services.AddScoped<IViewModelService<ProfileViewModel>, ProfileViewModelService>(); // 非泛型重载写法,效果和上面完全一致 services.AddScoped(typeof(IViewModelService<HomeViewModel>), typeof(HomeViewModelService)); services.AddScoped(typeof(IViewModelService<ProfileViewModel>), typeof(ProfileViewModelService));
补充说明
只有当你的实现类本身也是开放泛型时,才需要用开放泛型的注册方式,举个适用开放泛型注册的例子:
// 通用开放泛型实现 public class GenericViewModelService<T> : IViewModelService<T> where T : class { public Task<T> Get() { // 通用视图模型构造逻辑 return Task.FromResult<T>(default); } } // 开放泛型注册,容器会在请求IViewModelService<任意T>时自动生成对应封闭实现 services.AddScoped(typeof(IViewModelService<>), typeof(GenericViewModelService<>));
另外注意:你在服务构造函数中要注入DbContext的话,需要确保DbContext本身已经提前完成DI注册,否则服务解析时会抛出依赖缺失的异常。
内容的提问来源于stack exchange,提问作者enricosebastian
相关产品推荐
相关产品推荐

