在閱讀本文章以前,你能夠先閱讀:spa
事件總線是實現基於事件驅動模式的方式之一,事件發送者將事件消息發送到一個事件總線上,事件訂閱者向事件總線訂閱和接收事件,而後再處理接收到的事件。固然,訂閱者不只能夠接收和消費事件,它們自己也能夠建立事件,並將它們發送到事件總線上。code
事件總線是對發佈-訂閱模式的一種實現。它是一種集中式事件處理機制,容許不一樣的組件之間進行彼此通訊而又不須要相互依賴,達到一種解耦的目的。接口
首先,定義事件源、事件處理、事件總線接口。事件
namespace Example.EventBus { /// <summary> /// 事件源 /// </summary> public class IEvent { } } namespace Example.EventBus { /// <summary> /// 事件處理 /// </summary> /// <typeparam name="TEvent">事件源</typeparam> public interface IEventHandler<TEvent> where TEvent : IEvent { void Handle(TEvent @event); } } namespace Example.EventBus { /// <summary> /// 事件總線 /// </summary> public interface IEventBus { void Publish<TEvent>(TEvent @event) where TEvent : IEvent; void Subscribe<TEvent>(IEventHandler<TEvent> eventHandler) where TEvent : IEvent; void Unsubscribe<TEvent>(IEventHandler<TEvent> eventHandler) where TEvent : IEvent; } }
而後,實現具體事件總線類。get
private static Dictionary<string, List<object>> eventHandlers = new Dictionary<string, List<object>>();
public void Subscribe<TEvent>(IEventHandler<TEvent> eventHandler) where TEvent : IEvent { var eventTypeName = typeof(TEvent).FullName; if (eventAndEventHandlers.ContainsKey(eventTypeName)) { var handlers = eventAndEventHandlers[eventTypeName]; handlers.Add(eventHandler); } else { eventAndEventHandlers.Add(eventTypeName, new List<object> { eventHandler }); } }
public void Unsubscribe<TEvent>(IEventHandler<TEvent> eventHandler) where TEvent : IEvent { var eventTypeName = typeof(TEvent).FullName; if (eventAndEventHandlers.ContainsKey(eventTypeName)) { var handlers = eventAndEventHandlers[eventTypeName]; if (handlers != null && handlers.Exists(s => s.GetType()==eventHandler.GetType())) { var handlerToRemove = handlers.First(s => s.GetType() == eventHandler.GetType()); handlers.Remove(handlerToRemove); } } }
public void Publish<TEvent>(TEvent @event) where TEvent : IEvent { var eventTypeName = typeof(TEvent).FullName; if (eventAndEventHandlers.ContainsKey(eventTypeName)) { var handlers = eventAndEventHandlers[eventTypeName]; try { foreach (var handler in handlers) { MethodInfo meth = handler.GetType().GetMethod("Handle"); meth.Invoke(handler, new Object[] { @event }); } } catch (Exception ex) { throw ex; } } }
最後,建立客戶端類,具體事件源類,具體事件處理類。string
using Example.EventBus; using System; namespace Eaxmple.EventBus.Sample.ConsoleApp01 { /// <summary> /// 具體事件源類 /// </summary> public class SendedEvent : IEvent { public string Name { get; private set; } public SendedEvent(string name) { Name = name; } } /// <summary> /// 具體事件處理類顧客A /// </summary> public class CustomerASendedEventHandler : IEventHandler<SendedEvent> { public void Handle(SendedEvent @event) { Console.WriteLine($"顧客A收到{@event.Name}通知!"); } } /// <summary> /// 具體事件處理類顧客B /// </summary> public class CustomerBSendedEventHandler : IEventHandler<SendedEvent> { public void Handle(SendedEvent @event) { Console.WriteLine($"顧客B收到{@event.Name}通知!"); } } class Program { static void Main(string[] args) { var eventBus = new SampleEventBus(); var sendedEvent = new SendedEvent("優惠"); var customerASendedEventHandler = new CustomerASendedEventHandler(); eventBus.Subscribe<SendedEvent>(customerASendedEventHandler); var customerBSendedEventHandler = new CustomerBSendedEventHandler(); eventBus.Subscribe<SendedEvent>(customerBSendedEventHandler); Console.WriteLine($"商店發了{sendedEvent.Name}通知!"); eventBus.Publish<SendedEvent>(sendedEvent); Console.WriteLine(); eventBus.Unsubscribe<SendedEvent>(customerBSendedEventHandler); Console.WriteLine($"商店發了{sendedEvent.Name}通知!"); eventBus.Publish<SendedEvent>(sendedEvent); Console.ReadKey(); } } }
讓咱們來看看輸出結果:it
商店發佈優惠通知! 顧客A收到優惠通知。 顧客B收到優惠通知。 商店發佈優惠通知! 顧客A收到優惠通知。