Event Bus 与观察者模式在 C# (.NET) 中的实现与示例

面向初学者的在线Python训练器

轻松学习Python,无需理论负担。在浏览器中直接解决带自动检查的实践任务,无需安装任何东西。

开始课程

Event Bus 与观察者模式在 C# (.NET) 中:从理论到实践



在现代 C# (.NET) 开发中,系统组件之间的松耦合(loose coupling)是核心原则之一。观察者模式(Observer)及其演进——Event Bus(事件总线)——提供了一种优雅的机制,用于在对象之间组织交互,而无需直接依赖。本文将详细讲解如何在 C# (.NET) 中实现 Event Bus,分析其架构,并提供实际示例。



什么是观察者模式?

观察者模式定义了对象之间“一对多”的关系:当一个对象(主体)改变状态时,所有依赖它的对象(观察者)都会自动收到通知并更新。在 C# 中,该模式传统上通过事件(event)和委托来实现。



经典实现的问题

虽然 C# 内置的事件机制运行良好,但它存在一些限制:

  • 直接耦合:发布者必须显式知道订阅者。
  • 取消订阅困难:如果订阅者忘记取消订阅,会导致内存泄漏。
  • 灵活性有限:难以实现异步处理或事件过滤。


什么是 Event Bus?

Event Bus 是一个集中式总线(中介者),它实现了发布者-订阅者(Publisher-Subscriber)模式。与经典的观察者模式不同,发布者和订阅者彼此完全不知晓。它们仅通过总线进行通信:

  • 发布者 将消息(事件)发送到总线。
  • 总线 查找该事件类型的所有订阅者并通知它们。
  • 订阅者 注册到特定事件类型并处理它。


Event Bus 的优势

  • 松耦合:组件之间互不依赖。
  • 可扩展性:易于添加新的订阅者。
  • 可测试性:可以用模拟对象替换总线。
  • 异步性:可以在后台线程中处理事件。


在 C# (.NET) 中实现 Event Bus

让我们实现一个简单但功能完整的版本。创建一个 EventBus 类,用于存储订阅者字典。



public interface IEventBus{    void Publish<TEvent>(TEvent eventData) where TEvent : class;    IDisposable Subscribe<TEvent>(Action<TEvent> handler) where TEvent : class;}

public class EventBus : IEventBus{ private readonly Dictionary<Type, List<Delegate>> _subscribers = new(); private readonly object _lock = new();

public void Publish<TEvent>(TEvent eventData) where TEvent : class { List<Delegate> handlers; lock (_lock) { if (!_subscribers.TryGetValue(typeof(TEvent), out var list)) return; handlers = new List<Delegate>(list); }

foreach (var handler in handlers) { if (handler is Action<TEvent> action) action(eventData); } }

public IDisposable Subscribe<TEvent>(Action<TEvent> handler) where TEvent : class { lock (_lock) { if (!_subscribers.ContainsKey(typeof(TEvent))) _subscribers[typeof(TEvent)] = new List<Delegate>(); _subscribers[typeof(TEvent)].Add(handler); }

return new Unsubscriber(() => { lock (_lock) { if (_subscribers.TryGetValue(typeof(TEvent), out var list)) list.Remove(handler); }

推荐