首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> .NET 網頁程式設計 >> 關於.NET

EventBus 實作指南:XML 配置發布/訂閱、泛型處理器與反射動態調度

     編輯:關於.NET

受 CQRS 啟發,輕量級 EventBus 讓領域模型以 EventBus.Instance().Publish(new OrderAddedEvent()) 觸發事件,透過 XML 定義多對多訂閱關係,達成解耦。

解決方案結構

EventBus 專案結構

圖 1 專案結構:Events、EventHandlers、EventBus 核心

XML 事件映射配置

<Events>
  <Event>
    <PublishEvent>ConsoleApplication2.code.Events.OrderAddedEvent</PublishEvent>
    <SubscribedEvents>
      <SubscribedEvent>ConsoleApplication2.code.EventHandlers.OrderAddedEventHandler_CachePrepare</SubscribedEvent>
      <SubscribedEvent>ConsoleApplication2.code.EventHandlers.OrderAddedEventHandler_PDFGenerate</SubscribedEvent>
    </SubscribedEvents>
  </Event>
  <Event>
    <PublishEvent>ConsoleApplication2.code.Events.OrderDeletedEvent</PublishEvent>
    <SubscribedEvents>
      <SubscribedEvent>ConsoleApplication2.code.EventHandlers.OrderDeletedEventHandler_NotifyClient</SubscribedEvent>
      <SubscribedEvent>ConsoleApplication2.code.EventHandlers.OrderDeletedEventHandler_RemoveCache</SubscribedEvent>
    </SubscribedEvents>
  </Event>
</Events>

核心類別定義

public abstract class BaseEvent { }

public class OrderAddedEvent : BaseEvent { }
public class OrderDeletedEvent : BaseEvent {
    public Guid OrderId { get; set; }
    public OrderDeletedEvent(Guid orderId) { OrderId = orderId; }
}

public interface IEventHandler<T> where T : BaseEvent {
    void Handle(T evt);
}

public class OrderDeletedEventHandler_NotifyClient : IEventHandler<OrderDeletedEvent> {
    public void Handle(OrderDeletedEvent evt) {
        Console.WriteLine("[Order deleted] Notified.");
    }
}

啟動時載入 XML 建立映射字典

private static Dictionary<Type, List<Type>> eventMapping = 
    new Dictionary<Type, List<Type>>();

XElement root = XElement.Load(Path.Combine(
    AppDomain.CurrentDomain.BaseDirectory, "EventBus.xml"));

foreach (var evt in root.Elements("Event")) {
    var handlers = new List<Type>();
    Type publishType = Type.GetType(evt.Element("PublishEvent").Value);
    foreach (var sub in evt.Element("SubscribedEvents").Elements("SubscribedEvent")) {
        handlers.Add(Type.GetType(sub.Value));
    }
    eventMapping[publishType] = handlers;
}

發布與動態調度

public void Publish(BaseEvent evt) {
    var matches = from kv in eventMapping 
                  where kv.Key == evt.GetType() 
                  select kv;
    
    foreach (var pair in matches) {
        foreach (Type handlerType in pair.Value) {
            MethodInfo mi = handlerType.GetMethod("Handle");
            if (mi == null) continue;
            object handler = Activator.CreateInstance(handlerType);
            mi.Invoke(handler, new object[] { evt });
        }
    }
}

執行結果驗證

EventBus 執行輸出

圖 2 主控台輸出顯示兩個訂閱器依序處理事件

擴充建議:引入 IEventHandlerFactory 支援 DI 容器管理 Handler 生命週期;加入非同步 HandleAsync 避免阻塞發布執行緒。


作者:玄魂
出處:https://www.cnblogs.com/xuanhun/

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved