事件总线
----------2025年6月10日19:34:01
背景
之前谈到使用依赖注入+接口隔离,通过面向抽象的编程来实现同一解决方案中不同项目之间的互相通信的效果。但是,如果涉及到状态的传递的话,光用依赖注入我暂时没想到合适的解决方案,于是想到使用事件总线的方式来试试。其实用一般的事件应该也能够实现,但是秉着学习的态度,还是想用点没用过的东西来试试。
事件总线
事件总线是一种设计模式,用于在应用程序的不同组件之间传递事件。它允许组件之间进行松耦合的通信,而不需要直接引用对方。事件总线通常由一个中央事件处理程序组成,它接收事件并将其分发给适当的处理程序。 (暂时还没怎么了解这个,感觉就像是将一般的事件放到了一个共享的地方,然后通过某种方式将其进行管理,目前看到的是使用字典)
实现
定义事件总线:
//先整一个接口
public interface IEventBus
{
void Publish<T>(T @event);
void Subscribe<T>(Action<T> handler);
}
//定义具体的事件总线实现
public class EventBus : IEventBus
{
//T 指的是事件参数,通过事件参数的类型来判断当前执行的是什么事件
//比如:当事件参数为FormOpenEvent时,执行的事件为FormOpenEventHandler
private readonly Dictionary<Type, List<object>> _handlers = new();
public void Publish<T>(T @event)
{
//从字典中获取对应的事件处理器列表
if(_handlers.TryGetValue(typeof(T), out var handlers))
{
//可能会存在多个,所以通过遍历执行
foreach(var handler in handlers)
{
//转化为委托类型,并执行
((Action<T>)handler)(@event);
}
}
}
public void Subscribe<T>(Action<T> handler)
{
//获取事件类型,将其作为key
var eventType = typeof(T);
//判断字典中是否已经存在该事件类型的事件,如果不存在,则创建
if (!_handlers.ContainsKey(eventType))
{
_handlers[eventType] = new List<object>();
}
//将事件处理器添加到事件类型对应的事件处理器列表中
_handlers[eventType].Add(handler);
}
}
定义事件类型: 这个事件类型作为事件总线中字典的key,(我理解的)表示一个事件处理器的类型,即一个事件处理器(委托)对应一个类型
当事件没有返回值时,一个事件类型可以对应多个事件处理器(委托),可以形成多播委托的效果(一个发布,多个执行)。但是,当事件有返回值时,一个事件类型只能对应一个事件处理器(委托),因为多播委托只能够返回最后一个委托的返回值。