MediatR的INotificationHandler处理程序被多次调用如何解决?
问题原因
每次调用AddMediatR方法时,MediatR 9.x版本的默认逻辑会扫描你传入类型对应的整个程序集,将其中所有实现了INotificationHandler接口的类都注册到依赖注入容器中。如果你的StatusChangedEventHandler和CommandA、CommandB、CommandC处在同一个程序集,或是在这些类型对应程序集的扫描范围内,每调用一次AddMediatR就会重复注册一次该处理程序。当你发布通知时,MediatR会从容器中取出所有匹配的处理程序实例依次执行,因此调用次数和AddMediatR的调用次数完全对应。
解决方案
方案1:合并MediatR注册(最推荐)
不要多次调用AddMediatR,改为单次调用时传入所有需要扫描的类型/程序集即可,9.0版本的AddMediatR支持传入多个类型参数,示例如下:
// 单次注册传入所有需要扫描的程序集代表类型 services.AddMediatR(typeof(CommandA), typeof(CommandB), typeof(CommandC));
如果上述几个命令分别在不同程序集,且StatusChangedEventHandler仅属于其中一个程序集,这种写法也只会扫描一次Handler所在的程序集,不会重复注册。
方案2:指定扫描范围避免重复
如果你的项目是模块化结构,必须在不同模块中单独注册MediatR相关服务,可以在调用AddMediatR时显式过滤注册类型,保证每个AddMediatR调用只扫描当前模块独有的程序集,不要覆盖Handler所在的公共程序集,避免重复注册同一个Handler。
补充说明
如果排查发现Handler所在的程序集被多次传入扫描列表,直接移除重复的程序集引用即可。不要尝试通过修改Handler生命周期解决问题,重复注册的前提下即使是单例,也会被多次取出执行。
内容的提问来源于stack exchange,提问作者Vladimir Zotov

