实现简易Mediator模式时DI容器无注册服务异常排查
解决方案
问题根源在于你的Send方法试图获取针对IRequest<TResponse>的处理器,但你实际注册的是针对具体请求类型Request的处理器。DI容器无法自动将IRequestHandler<Request, string>转换为IRequestHandler<IRequest<string>, string>——泛型接口的协变逆变规则在这里不支持这种匹配。
修复Sender的Send方法
修改Send方法,通过反射获取请求的实际类型,动态匹配并调用对应的处理器:
class Sender : ISender { private readonly IServiceProvider _serviceProvider; public Sender(IServiceProvider serviceProvider) { _serviceProvider = serviceProvider; } public TResponse Send<TResponse>(IRequest<TResponse> request) { // 获取请求的真实运行时类型 var actualRequestType = request.GetType(); // 构造对应的处理器接口类型 var handlerInterfaceType = typeof(IRequestHandler<,>).MakeGenericType(actualRequestType, typeof(TResponse)); // 从DI容器中获取处理器实例 var handler = _serviceProvider.GetRequiredService(handlerInterfaceType); // 反射调用Handle方法并返回结果 var handleMethod = handlerInterfaceType.GetMethod(nameof(IRequestHandler<object, object>.Handle)); return (TResponse)handleMethod.Invoke(handler, new[] { request }); } }
优化服务注册(可选)
如果项目中有大量请求和处理器,可以通过反射批量注册,省去手动逐个添加的麻烦:
IServiceCollection services = new ServiceCollection(); services.AddScoped<ISender, Sender>(); // 扫描程序集,批量注册所有IRequestHandler实现类 var handlerImplementations = AppDomain.CurrentDomain.GetAssemblies() .SelectMany(assembly => assembly.GetTypes()) .Where(type => !type.IsAbstract && !type.IsInterface && type.GetInterfaces().Any(i => i.IsGenericType && i.GetGenericTypeDefinition() == typeof(IRequestHandler<,>))); foreach (var handlerType in handlerImplementations) { var matchingInterface = handlerType.GetInterfaces() .First(i => i.IsGenericType && i.GetGenericTypeDefinition() == typeof(IRequestHandler<,>)); services.AddScoped(matchingInterface, handlerType); }
验证调用
现在你可以正常使用_sender.Send(new Request());,DI会正确匹配到RequestHandler并执行,返回预期的"OK"结果。
内容的提问来源于stack exchange,提问作者Vedran Knezevic
相关产品推荐
相关产品推荐

