事件总线(EventBus)的Demo实践
一、前言
事件是基于委托的发布-订阅机制(基于windows消息处理机制)通过定义事件,订阅事件、发布事件并且关联业务逻辑,实现系统业务的解耦。发布-订阅机制提供了一种天然的业务解耦方式,所以在系统中使用事件定义业务状态、业务场景,让关联的业务订阅事件,当事件产生时事件订阅者执行业务,这样发布者不必知道订阅者具体的细节、订阅者也不必了解发布者。但是简单的事件无法满足实际生产的使用,因为生产中的业务是复杂的,多样的,所以就要设计一种框架来统一管理事件设计成事件总线。
二、设计
事件总线进行抽象成如下接口关系图,IEventBus作为事件总线进行协调管理事件的发布订阅,作为事件中心承担的职责除了事件的发布和订阅之外,还包括对事件存储、容错、路由、异步、重试等。
事件总线类说明 | |
IEvent | 事件载体的接口,所有事件继承该接口,定义一个事件,并且赋予事件相应的业务逻辑,比如这个事件要产生的业务操作 |
IEventHandler | 事件处理接口,每一个事件都必须关联相应的事件操作 |
IEventSubscriber | 发布订阅机制的订阅事件接口,主要功能订阅事件关联事件处理器 |
IEventPublisher | 发布订阅机制的发布事件接口,主要功能对产生的事件进行发布 |
IEventBus | 事件总线接口,通过聚合事件的发布和订阅接口,在内部抽象成一个总线的方式统一管理事件,并且引入事件消息存储结构 |
三、代码
依据上述的事件总线接口关系图,在代码上定义各接口类,然后定义接口的关系创建一个初步的事件总线,通过事件总线接口来实现具体事件总线框架。
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace TQF.EventBus.EventFramwork { /// <summary> /// 事件消息接口,定义一个事件,事件载体 /// </summary> public interface IEvent { /// <summary> /// 事件Id /// </summary> Guid EventId { get; } /// <summary> /// 事件时间 /// </summary> DateTime EventDate { get; } } }
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading; using System.Threading.Tasks; namespace TQF.EventBus.EventFramwork { /// <summary> /// 事件处理接口,定义一个事件对应的处理逻辑 /// </summary> public interface IEventHandler { /// <summary> /// 定义事件异步的处理器 /// </summary> /// <param name="event">使用@区分关键字</param> /// <param name="cancellationToken">任务取消令牌,取消任务</param> /// <returns></returns> Task<bool> HandlerAsync(IEvent @event, CancellationToken cancellationToken = default); bool CanHandle(IEvent @event); } /// <summary> /// 泛型事件处理器 /// </summary> /// <typeparam name="T"></typeparam> public interface IEventHandler<in T> : IEventHandler where T : IEvent { Task<bool> HandleAsync(T @event, CancellationToken cancellationToken = default); } }
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading; using System.Threading.Tasks; namespace TQF.EventBus.EventFramwork { /// <summary> /// 事件发布器,发布消息 /// </summary> public interface IEventPublisher:IDisposable { /// <summary> /// 事件发布器,发布事件 /// </summary> /// <typeparam name="TEvent"></typeparam> /// <param name="event">事件</param> /// <param name="cancellationToken">任务取消令牌,取消任务</param> /// <returns></returns> Task PublishAsync<TEvent>(TEvent @event, CancellationToken cancellationToken = default) where TEvent : IEvent; } }
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace TQF.EventBus.EventFramwork { /// <summary> /// 事件订阅器订阅消息 /// </summary> public interface IEventSubscriber:IDisposable { void Subscriber(); } }
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace TQF.EventBus.EventFramwork { /// <summary> /// 事件总线接口,定义事件通讯渠道,消息订阅功能,消息派发功能(消息的路由,过滤,选择)等。 /// 通过事件总线管理两者 /// </summary> public interface IEventBus:IEventPublisher,IEventSubscriber { } }
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace TQF.EventBus.EventFramwork { /// <summary> /// 定义事件传递的参数 /// </summary> public class EventProcessedEventArgs:EventArgs { public IEvent Event { get; } public EventProcessedEventArgs(IEvent @event) { this.Event = @event; } } }
四、总结
1、事件总线的目的是对业务的解耦,通过设计合理的架构来达到这个目标,既然是合理的框架,就涉及到存储、容错、路由、异步、重试等问题,所以上述提供是一个事件总线雏形。
2、对于模式和架构,一个模式,一个架构其构成的最小单位可以理解为对象,通过对对象的划分、割裂,单独成个体,通过关系连接这些个体,建立起一个模型->模式->架构。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?