核心是用多态替代硬编码依赖,让事件发布者和订阅者面向抽象交互:定义统一ievent接口与泛型eventprocessor基类,事件仅承载不可变事实,处理器专注业务逻辑;运行时自动扫描注册、按类型分发,新增事件及处理器无需修改旧代码,支持插件式部署、版本兼容与独立测试。

核心是用多态替代硬编码依赖,让事件发布者和订阅者只面向抽象交互,新增类型无需改旧代码。
定义统一事件接口与处理器基类
所有事件必须实现同一接口(如 IEvent),含唯一 ID、时间戳、版本号等基础字段;所有处理器继承抽象基类(如 EventProcessor
- 事件类不包含业务逻辑,仅承载不可变事实(如 OrderCreatedEvent)
- 处理器基类提供公共能力:日志记录、异常包装、上下文传递,但不决定“做什么”
- 避免在基类中写 if-else 判断事件类型——那是多态要解决的问题
运行时按需加载并注册处理器
启动时扫描程序集,自动发现所有继承自 EventProcessor
- 新增一种事件,只需新增一个事件类 + 一个对应处理器,不改调度器代码
- 支持插件式部署:把新处理器打成独立 DLL,运行时动态加载并注册
- 可配合配置文件或注解(如 [Handles(typeof(InventoryUpdatedEvent))])控制启用状态
发布端完全不知晓订阅者存在
发布者调用 eventBus.Publish(event) 即完成职责。eventBus 内部根据 event.GetType() 查找所有匹配的处理器实例,以异步方式并行调用其 HandleAsync 方法。每个处理器自行决定是否重试、降级或转发下游事件。
- 发布者不引用任何处理器项目,也不依赖 DI 容器解析订阅者
- 处理器之间无调用链,失败互不影响;一个挂了,其他照常执行
- 若需顺序保障,由事件本身携带序列号,处理器自行做本地排序或去重
用契约+版本控制保障演进安全
事件类命名带版本(如 PaymentProcessedV2),处理器明确标注支持的版本范围。调度器在分发前校验兼容性,拒绝不匹配的事件。老版本处理器仍可运行,新版本事件可被新处理器消费,两者共存过渡。
- 禁止修改已有事件字段语义(如把 “amount” 从元改为分)
- 新增字段设为可空或提供默认值,保证反序列化不崩溃
- 测试时可直接 new 一个事件对象传给单个处理器,验证行为,无需启动整个网











