.NET Core 7中如何通过反射正确注册泛型ICommandHandler实现类
.NET Core 7 命令与命令处理程序的原生批量依赖注入注册方案
问题背景
你的命令与命令处理程序结构如下:
public abstract class Command {} public interface ICommandHandler<TCommand> where TCommand: Command {} public class SignUpCommand: Command {} public class SignUpCommandHandler<TCommand> : ICommandHandler<TCommand> where TCommand : SignUpCommand {}
手动注册ICommandHandler<SignUpCommand>与SignUpCommandHandler<SignUpCommand>的映射可以正常运行,但通过反射批量注册时,直接获取接口或使用泛型定义会出现泛型约束违反或注册报错的问题。
正确的批量注册实现
以下是.NET Core 7原生的批量注册方案,通过精准识别处理程序与命令的泛型映射关系,确保注册的映射与手动注册完全一致:
using System.Reflection; using Microsoft.Extensions.DependencyInjection; // 替换为包含命令和处理程序的目标程序集 var targetAssembly = Assembly.GetExecutingAssembly(); // 筛选所有符合条件的命令处理程序类型 var commandHandlerTypes = targetAssembly.GetTypes() .Where(t => t.IsClass && !t.IsAbstract && t.IsGenericType) .Where(t => t.GetInterfaces() .Any(i => i.IsGenericType && i.GetGenericTypeDefinition() == typeof(ICommandHandler<>))); foreach (var handlerType in commandHandlerTypes) { // 获取当前处理程序实现的ICommandHandler<>接口 var commandHandlerInterface = handlerType.GetInterfaces() .First(i => i.IsGenericType && i.GetGenericTypeDefinition() == typeof(ICommandHandler<>)); // 提取接口对应的具体命令类型(如SignUpCommand) var commandType = commandHandlerInterface.GetGenericArguments()[0]; // 构造处理程序的具体泛型实例类型(如SignUpCommandHandler<SignUpCommand>) var concreteHandler = handlerType.MakeGenericType(commandType); // 以Scoped生命周期注册映射,与手动注册保持一致 services.AddScoped(commandHandlerInterface, concreteHandler); }
方案说明
- 类型筛选:先筛选出程序集中所有非抽象的泛型类,且这些类实现了
ICommandHandler<>泛型接口。 - 接口识别:精准定位处理程序实现的
ICommandHandler<TCommand>接口,避免误取其他接口。 - 泛型实例构造:通过接口的泛型参数拿到具体命令类型,再构造处理程序的具体泛型实例,确保映射关系符合泛型约束。
- 生命周期对齐:使用与手动注册一致的
Scoped生命周期,保证DI容器的行为一致性。
内容的提问来源于stack exchange,提问作者Siamak Ferdos
相关产品推荐
相关产品推荐

