各模块能否自行注册MediatR处理器,还是必须在启动程序中统一注册?
问题结论
多次调用AddMediatR并传入不同模块的程序集是完全可行的,不会产生注册异常,完全可以实现各模块自行注册专属处理器的模块化架构要求。
底层逻辑说明
MediatR的AddMediatR扩展方法内部采用追加式的注册逻辑:扫描传入程序集内的请求处理器、通知处理器、管道行为等组件后,会将服务注册添加到DI容器中,不会覆盖之前已完成的MediatR相关注册。只要不同模块没有重复注册同一个请求的专属处理器,就不会出现逻辑冲突。
模块化注册实现方案
- 每个模块单独定义
IServiceCollection扩展方法,在方法内部完成本模块的所有服务注册,包括MediatR注册:
// ModuleA 项目内的扩展类 public static class ModuleAServiceExtensions { public static IServiceCollection AddModuleA(this IServiceCollection services) { // 注册当前模块的MediatR组件 // MediatR 11及更早版本写法 services.AddMediatR(typeof(ModuleAServiceExtensions).Assembly); // MediatR 12及之后版本写法 // services.AddMediatR(cfg => cfg.RegisterServicesFromAssembly(typeof(ModuleAServiceExtensions).Assembly)); // 此处可添加ModuleA专属的其他服务注册,如仓储、数据库上下文等 return services; } }
ModuleB按照相同逻辑实现AddModuleB扩展方法即可。
- 顶层启动项目只需要引用各模块,调用对应的扩展方法完成注册:
var builder = WebApplication.CreateBuilder(args); // 按模块注册服务,无需关心模块内部的MediatR注册细节 builder.Services.AddModuleA(); builder.Services.AddModuleB(); // 其他顶层服务注册逻辑 var app = builder.Build(); // 中间件配置、启动逻辑 app.Run();
注意事项
- 若不同模块需要注册同一个通知的多个处理器,多次调用
AddMediatR的方式正好匹配该场景,所有注册的处理器都会被正常触发 - 不要在不同模块中重复注册同一个请求的处理器,否则DI容器会注入多个处理器,不符合单请求单处理器的常规设计预期
- 注意适配自己项目使用的MediatR版本,12+版本调整了
AddMediatR的入参格式,需要用配置委托的方式注册程序集
内容的提问来源于stack exchange,提问作者tlt
相关产品推荐
相关产品推荐

