在阅读本文章以前,你能够先阅读: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收到优惠通知。