C# (.NET)中的事件总线与观察者模式:微服务与GUI实现

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

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

开始课程

C# (.NET)中的事件总线与观察者模式:从理论到实现



在现代C# (.NET)开发中,经常需要组织系统组件之间的交互,同时保持它们的独立性。观察者模式及其演进——事件总线——是实现松耦合的关键工具。在本文中,我们将深入探讨这些机制的工作原理,并用C#创建一个简单但功能完善的事件总线实现。



观察者模式:经典方法



观察者模式定义了对象之间“一对多”的关系:当一个对象(发布者)改变其状态时,所有依赖对象(订阅者)都会自动收到通知。在.NET中,该模式通过事件(event)和委托内置实现。



经典实现的缺点:

  • 订阅者对发布者的直接依赖(需要存储对象引用)。
  • 在大型系统中管理订阅的复杂性。
  • 线程问题(多线程需要额外的同步)。


事件总线:集中式中介者



事件总线通过充当集中式中介者来解决这些问题。组件不再直接订阅特定对象,而是在事件总线中注册。发布者将事件发布到总线,总线再将事件分发给所有订阅者。这实现了发布/订阅模式。



事件总线的优势:

  • 松耦合:发布者和订阅者彼此互不了解。
  • 可扩展性:易于添加新的订阅者。
  • 通用性:适用于GUI(WPF/WinForms)、微服务和游戏(Unity)。


C# (.NET)中事件总线的实现



我们将创建一个基础的事件总线实现,支持异步处理和类型化事件。为此,我们将使用IEvent接口和泛型类EventBus。



步骤1:定义基础类型。

// 所有事件的基础接口public interface IEvent { }

// 示例事件 - 用户消息public class UserCreatedEvent : IEvent{ public int UserId { get; } public string Email { get; }

public UserCreatedEvent(int userId, string email) { UserId = userId; Email = email; }}


步骤2:创建事件总线。

using System;using System.Collections.Concurrent;using System.Threading.Tasks;

public class EventBus{ // 订阅者存储:键 - 事件类型,值 - 处理器列表 private readonly ConcurrentDictionary<Type, ConcurrentBag<object>> _subscribers = new();

// 订阅事件 public void Subscribe<TEvent>(Func<TEvent, Task> handler) where TEvent : IEvent { var eventType = typeof(TEvent); var handlers = _subscribers.GetOrAdd(eventType, _ => new ConcurrentBag<object>()); handlers.Add(handler); }

// 取消订阅(简化版 - 删除该类型的所有处理器) public void Unsubscribe<TEvent>() where TEvent : IEvent { _subscribers.TryRemove(typeof(TEvent), out _); }

// 发布事件(异步) public async Task PublishAsync<TEvent>(TEvent eventData) where TEvent : IEvent { if (!_subscribers.TryGetValue(typeof(TEvent), out var handlers)) return;

foreach (var handler in handlers) { if (handler is Func<TEvent, Task> typedHandler) { await typedHandler(eventData); } } }}


步骤3:在应用程序中使用。

public class                    

推荐