如何正确注册MediatR的泛型IRequestHandler请求处理器
解决方案
错误根因
你遇到的异常是两个原因共同导致的:
- MediatR 默认的扫描注册逻辑仅支持自动注册闭合泛型/非泛型的Handler,不会自动识别开放泛型的Handler实现
- 你手动注册开放泛型Handler时,DI容器无法正确匹配
IRequestHandler<,>(2个泛型参数)和GetAccessesHandler<>(1个泛型参数)的泛型参数映射关系,导致构造时抛出参数数量不匹配的异常
修复方案
方案1:手动注册闭合泛型Handler(适用实体数量少的场景)
如果你用到的实体类型不多,直接为每个用到的实体注册对应闭合类型的Handler即可,稳定无歧义:
// 以Telephone实体为例,每新增一个用到的实体加一行对应注册 services.AddTransient<IRequestHandler<GetAccessesQuery<Telephone>, ObjectAccessesResponse>, GetAccessesHandler<Telephone>>();
注意:请删除原来的services.AddTransient(typeof(IRequestHandler<,>), typeof(GetAccessesHandler<>));这行代码,避免冲突
方案2:反射批量注册(适用实体数量多的场景)
如果有大量继承自EntityBase的实体需要用到这个泛型Handler,可以用反射批量扫描注册:
// 扫描所有继承自EntityBase的非抽象实体类 var entityTypes = typeof(EntityBase).Assembly.GetTypes() .Where(t => t.IsClass && !t.IsAbstract && t.IsSubclassOf(typeof(EntityBase))); foreach (var entityType in entityTypes) { var closedQueryType = typeof(GetAccessesQuery<>).MakeGenericType(entityType); var closedHandlerType = typeof(GetAccessesHandler<>).MakeGenericType(entityType); var closedHandlerInterface = typeof(IRequestHandler<,>).MakeGenericType(closedQueryType, typeof(ObjectAccessesResponse)); services.AddTransient(closedHandlerInterface, closedHandlerType); }
同样要删除原来的开放泛型Handler注册代码。
额外检查项
确认AddMediatR已经包含了泛型Query和Handler所在的程序集,避免扫描遗漏:
// 如果GetAccessesQuery和Handler和ValidationBehavior不在同一个程序集,需要额外加对应程序集 services.AddMediatR( typeof(ValidationBehavior<,>).Assembly, typeof(GetAccessesQuery<>).Assembly );
内容的提问来源于stack exchange,提问作者lemon
相关产品推荐
相关产品推荐

