什麼是事件總線

1 前置閱讀

在閱讀本文章以前,你能夠先閱讀:spa

  • 什麼是觀察者模式

2 定義

事件總線是實現基於事件驅動模式的方式之一,事件發送者將事件消息發送到一個事件總線上,事件訂閱者向事件總線訂閱和接收事件,而後再處理接收到的事件。固然,訂閱者不只能夠接收和消費事件,它們自己也能夠建立事件,並將它們發送到事件總線上。code

事件總線是對發佈-訂閱模式的一種實現。它是一種集中式事件處理機制,容許不一樣的組件之間進行彼此通訊而又不須要相互依賴,達到一種解耦的目的。接口

3 需求

  • 維護一個事件源與事件處理的映射字典。
  • 提供統一的訂閱、取消訂閱和發佈接口。

3 實現

首先,定義事件源、事件處理、事件總線接口。事件

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

  1. 事件源與事件處理的映射字典。
private static Dictionary<string, List<object>> eventHandlers = new Dictionary<string, List<object>>();
  1. 實現訂閱,往字典表中添加事件處理實例
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 });
    }
}
  1. 實現取消訂閱,從字典表中刪除事件處理實例
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);
        }
    }
}
  1. 實現發佈,經過事件源找到對應的事件處理類,並執行它
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收到優惠通知。
相關文章
相關標籤/搜索