如何通过反射在MS DI中批量注册多变体泛型ServiceResult<T>
在MS DI中批量注册ServiceResult所有变体的解决方案
可以实现批量注册,核心思路是通过反射扫描应用中所有依赖ServiceResult<T>的类型,提取出所有被使用的泛型参数T,再为每个T注册对应的ServiceResult<T>实例。
具体实现步骤
扫描程序集,提取所有被使用的T类型
遍历目标程序集(比如你的BusinessLogic.Services)中所有类的构造函数、属性、字段,找出所有ServiceResult<>的具体泛型实例,提取其泛型参数T并去重。批量注册到MS DI容器
针对每个提取到的T,将ServiceResult<T>注册为自身的实现(因为没有接口,直接注册类本身)。
完整代码示例
在你的DI配置代码中(比如Program.cs或Startup.cs)添加以下逻辑:
// 获取ServiceResult<T>的泛型定义 Type serviceResultGenericDef = typeof(ServiceResult<>); // 获取需要扫描的目标程序集(替换为你的业务逻辑程序集名称) Assembly targetAssembly = AppDomain.CurrentDomain.GetAssemblies() .FirstOrDefault(a => a.GetName().Name == "BusinessLogic.Services"); if (targetAssembly == null) { throw new InvalidOperationException("未找到目标程序集"); } // 存储所有找到的独特T类型 HashSet<Type> usedGenericArguments = new HashSet<Type>(); // 遍历目标程序集中的所有非抽象、非接口类型 foreach (Type type in targetAssembly.GetTypes() .Where(t => !t.IsAbstract && !t.IsInterface)) { // 检查构造函数参数 foreach (ConstructorInfo ctor in type.GetConstructors(BindingFlags.Public | BindingFlags.Instance)) { foreach (ParameterInfo param in ctor.GetParameters()) { CheckAndAddGenericArgument(param.ParameterType); } } // 检查公共属性 foreach (PropertyInfo prop in type.GetProperties(BindingFlags.Public | BindingFlags.Instance)) { CheckAndAddGenericArgument(prop.PropertyType); } // 检查公共字段 foreach (FieldInfo field in type.GetFields(BindingFlags.Public | BindingFlags.Instance)) { CheckAndAddGenericArgument(field.FieldType); } } // 批量注册每个ServiceResult<T> foreach (Type t in usedGenericArguments) { Type concreteType = serviceResultGenericDef.MakeGenericType(t); // 根据业务需求选择生命周期,这里用Transient,可替换为Scoped/Singleton builder.Services.AddTransient(concreteType); } // 辅助方法:检查类型是否为ServiceResult<>的实例,提取泛型参数 void CheckAndAddGenericArgument(Type type) { // 处理普通泛型实例 if (type.IsGenericType && type.GetGenericTypeDefinition() == serviceResultGenericDef) { Type genericArg = type.GetGenericArguments()[0]; usedGenericArguments.Add(genericArg); } // 处理可空值类型(比如ServiceResult<ErrorCode>?) else if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable<>)) { Type underlyingType = Nullable.GetUnderlyingType(type); if (underlyingType != null && underlyingType.IsGenericType && underlyingType.GetGenericTypeDefinition() == serviceResultGenericDef) { Type genericArg = underlyingType.GetGenericArguments()[0]; usedGenericArguments.Add(genericArg); } } }
关键说明
- 代码会扫描目标程序集中所有类的构造函数参数、公共属性、公共字段,确保不会遗漏任何被依赖的
ServiceResult<T>变体。 - 使用
HashSet<Type>存储泛型参数T,自动去重,避免重复注册。 - 支持处理可空值类型的
ServiceResult<T>?场景。 - 生命周期选择
Transient,可根据实际业务需求替换为Scoped或Singleton。
原有代码未生效的原因
你之前的代码仅扫描了名称以CommandService结尾的类型并获取其接口,但没有关联到ServiceResult<T>的泛型参数提取逻辑,因此无法定位到需要注册的具体ServiceResult<T>变体。上述方案直接针对ServiceResult<T>的依赖关系扫描,能准确捕获所有被使用的泛型参数。
内容的提问来源于stack exchange,提问作者Anton Griduhsko
相关产品推荐
相关产品推荐

