首页
/ MediatR中处理多个通知事件的通用模式

MediatR中处理多个通知事件的通用模式

2025-05-20 06:05:34作者:霍妲思

在MediatR项目中,开发者经常遇到需要处理多个类似通知事件的情况。本文探讨如何优雅地实现一个通用处理器来处理多个相关事件,避免代码重复。

问题背景

当使用MediatR处理领域事件时,经常会遇到多个事件需要执行相同或类似逻辑的场景。例如,在一个测试管理系统中,可能有TestResultRenamedTestResultTestCreatedTestResultTestCommentChanged等多种事件,它们都需要执行相同的后续处理逻辑。

传统做法是为每个事件类型单独实现一个处理器方法,导致大量重复代码:

public Task Handle(TestResultTestParameterAdded notification, CancellationToken cancellationToken)
    => HandleTestResultEvent(notification, cancellationToken);

public Task Handle(TestResultTestParameterRemoved notification, CancellationToken cancellationToken)
    => HandleTestResultEvent(notification, cancellationToken);

解决方案

1. 使用基类事件

最优雅的解决方案是让所有相关事件继承自一个公共基类,然后实现一个处理该基类的通用处理器:

// 定义基类事件
public abstract class TestResultEvent : INotification
{
    // 公共属性
}

// 具体事件继承基类
public class TestResultRenamed : TestResultEvent { /*...*/ }
public class TestResultTestCreated : TestResultEvent { /*...*/ }

// 通用处理器
public class TestResultContextSubscriber : INotificationHandler<TestResultEvent>
{
    public Task Handle(TestResultEvent notification, CancellationToken cancellationToken)
    {
        // 通用处理逻辑
        return HandleTestResultEvent(notification, cancellationToken);
    }
}

2. 注册服务

确保正确注册处理器服务:

services.AddScoped<INotificationHandler<TestResultEvent>, TestResultContextSubscriber>();

3. 工作原理

当发布任何继承自TestResultEvent的事件时,MediatR会自动调用这个通用处理器。同时,如果某些事件需要特殊处理,仍然可以保留它们特定的处理器。

注意事项

  1. 事件继承关系:确保所有需要通用处理的事件都正确继承自基类事件。

  2. 处理器优先级:MediatR会同时调用特定事件处理器和基类事件处理器,执行顺序取决于注册顺序。

  3. 性能考虑:这种模式不会带来额外性能开销,因为MediatR内部已经优化了通知分发机制。

  4. 异常处理:在通用处理器中实现统一的异常处理逻辑,可以简化错误处理流程。

高级用法

对于更复杂的场景,可以结合策略模式:

public class TestResultContextSubscriber : INotificationHandler<TestResultEvent>
{
    private readonly Dictionary<Type, Action<TestResultEvent>> _handlers;
    
    public TestResultContextSubscriber()
    {
        _handlers = new Dictionary<Type, Action<TestResultEvent>>
        {
            { typeof(TestResultRenamed), e => HandleRenamed((TestResultRenamed)e) },
            { typeof(TestResultTestCreated), e => HandleCreated((TestResultTestCreated)e) }
        };
    }
    
    public Task Handle(TestResultEvent notification, CancellationToken cancellationToken)
    {
        if(_handlers.TryGetValue(notification.GetType(), out var handler))
        {
            handler(notification);
        }
        else
        {
            // 默认处理逻辑
        }
        return Task.CompletedTask;
    }
}

这种模式在保持代码整洁的同时,提供了足够的灵活性来处理各种事件场景。

登录后查看全文
热门项目推荐

项目优选

收起
ohos_react_nativeohos_react_native
React Native鸿蒙化仓库
C++
176
261
RuoYi-Vue3RuoYi-Vue3
🎉 (RuoYi)官方仓库 基于SpringBoot,Spring Security,JWT,Vue3 & Vite、Element Plus 的前后端分离权限管理系统
Vue
860
511
ShopXO开源商城ShopXO开源商城
🔥🔥🔥ShopXO企业级免费开源商城系统,可视化DIY拖拽装修、包含PC、H5、多端小程序(微信+支付宝+百度+头条&抖音+QQ+快手)、APP、多仓库、多商户、多门店、IM客服、进销存,遵循MIT开源协议发布、基于ThinkPHP8框架研发
JavaScript
93
15
openGauss-serveropenGauss-server
openGauss kernel ~ openGauss is an open source relational database management system
C++
129
182
openHiTLSopenHiTLS
旨在打造算法先进、性能卓越、高效敏捷、安全可靠的密码套件,通过轻量级、可剪裁的软件技术架构满足各行业不同场景的多样化要求,让密码技术应用更简单,同时探索后量子等先进算法创新实践,构建密码前沿技术底座!
C
259
300
kernelkernel
deepin linux kernel
C
22
5
cherry-studiocherry-studio
🍒 Cherry Studio 是一款支持多个 LLM 提供商的桌面客户端
TypeScript
596
57
CangjieCommunityCangjieCommunity
为仓颉编程语言开发者打造活跃、开放、高质量的社区环境
Markdown
1.07 K
0
HarmonyOS-ExamplesHarmonyOS-Examples
本仓将收集和展示仓颉鸿蒙应用示例代码,欢迎大家投稿,在仓颉鸿蒙社区展现你的妙趣设计!
Cangjie
398
371
Cangjie-ExamplesCangjie-Examples
本仓将收集和展示高质量的仓颉示例代码,欢迎大家投稿,让全世界看到您的妙趣设计,也让更多人通过您的编码理解和喜爱仓颉语言。
Cangjie
332
1.08 K