C#中DI容器注入带构造参数的泛型接口问题
泛型服务带构造参数的DI注册方案
问题代码
public interface A<T> { T GetValue(); } public class B<T> : A<T> { private readonly string _key; public B(string key) { _key = key; } public T GetValue() { return default(T); } }
直接使用services.AddScoped(typeof(A<>), typeof(B<>))注册会报错,原因是DI容器无法自动解析B<T>构造函数中的string key参数。以下是几种可行的注册方案:
方案1:使用固定key注册开放泛型
如果所有B<T>实例共用同一个固定key,可通过工厂委托创建实例:
services.AddScoped(typeof(A<>), (provider, serviceType) => { // 获取当前要解析的封闭泛型类型的参数(比如A<string>的参数是string) var genericArgs = serviceType.GetGenericArguments(); // 创建对应的B<T>封闭泛型类型 var bImplementationType = typeof(B<>).MakeGenericType(genericArgs); // 替换为你的固定key值 return Activator.CreateInstance(bImplementationType, "your-fixed-key") as object; });
方案2:从其他服务动态获取key
如果key需要从DI容器内的其他服务(比如配置服务)获取,可在工厂委托中解析依赖:
// 先注册提供key的服务(示例) services.AddScoped<IConfigService, ConfigService>(); services.AddScoped(typeof(A<>), (provider, serviceType) => { var configService = provider.GetRequiredService<IConfigService>(); // 根据泛型参数动态获取对应key(示例逻辑) string targetKey = configService.GetKeyForType(serviceType.GetGenericArguments()[0]); var genericArgs = serviceType.GetGenericArguments(); var bImplementationType = typeof(B<>).MakeGenericType(genericArgs); return Activator.CreateInstance(bImplementationType, targetKey) as object; });
方案3:为特定泛型版本单独注册
如果只需要为特定的T类型注册对应的服务,可直接指定封闭泛型类型并传入key:
// 为A<string>注册B<string>,指定专属key services.AddScoped<A<string>>(_ => new B<string>("string-type-key")); // 为A<int>注册B<int>,指定专属key services.AddScoped<A<int>>(_ => new B<int>("int-type-key"));
内容的提问来源于stack exchange,提问作者Manoj Lobo
相关产品推荐
相关产品推荐

