設計系列-事件總線(EventBus)


一、前言

  事件是基於委托的發布-訂閱機制(基於windows消息處理機制)通過定義事件,訂閱事件、發布事件並且關聯業務邏輯,實現系統業務的解耦。發布-訂閱機制提供了一種天然的業務解耦方式,所以在系統中使用事件定義業務狀態、業務場景,讓關聯的業務訂閱事件,當事件產生時事件訂閱者執行業務,這樣發布者不必知道訂閱者具體的細節、訂閱者也不必了解發布者。但是簡單的事件無法滿足實際生產的使用,因為生產中的業務是復雜的,多樣的,所以就要設計一種框架來統一管理事件設計成事件總線。

二、設計

  

 

  事件總線進行抽象成如下接口關系圖,IEventBus作為事件總線進行協調管理事件的發布訂閱,作為事件中心承擔的職責除了事件的發布和訂閱之外,還包括對事件存儲、容錯、路由、異步、重試等。

事件總線類說明
IEvent 事件載體的接口,所有事件繼承該接口,定義一個事件,並且賦予事件相應的業務邏輯,比如這個事件要產生的業務操作
IEventHandler 事件處理接口,每一個事件都必須關聯相應的事件操作
IEventSubscriber 發布訂閱機制的訂閱事件接口,主要功能訂閱事件關聯事件處理器
IEventPublisher 發布訂閱機制的發布事件接口,主要功能對產生的事件進行發布
IEventBus 事件總線接口,通過聚合事件的發布和訂閱接口,在內部抽象成一個總線的方式統一管理事件,並且引入事件消息存儲結構

 三、代碼

  依據上述的事件總線接口關系圖,在代碼上定義各接口類,然后定義接口的關系創建一個初步的事件總線,通過事件總線接口來實現具體事件總線框架。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace TQF.EventBus.EventFramwork
{

    /// <summary>
    /// 事件消息接口,定義一個事件,事件載體
    /// </summary>
    public interface IEvent
    {
        /// <summary>
        /// 事件Id
        /// </summary>
        Guid EventId { get; }

        /// <summary>
        /// 事件時間
        /// </summary>
        DateTime EventDate { get; }
    }
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace TQF.EventBus.EventFramwork
{
    /// <summary>
    /// 事件處理接口,定義一個事件對應的處理邏輯
    /// </summary>
    public interface IEventHandler
    {
        /// <summary>
        /// 定義事件異步的處理器
        /// </summary>
        /// <param name="event">使用@區分關鍵字</param>
        /// <param name="cancellationToken">任務取消令牌,取消任務</param>
        /// <returns></returns>
        Task<bool> HandlerAsync(IEvent @event, CancellationToken cancellationToken = default);
        bool CanHandle(IEvent @event);
    }

    /// <summary>
    /// 泛型事件處理器
    /// </summary>
    /// <typeparam name="T"></typeparam>
    public interface IEventHandler<in T> : IEventHandler where T : IEvent
    {
        Task<bool> HandleAsync(T @event, CancellationToken cancellationToken = default);
    }
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace TQF.EventBus.EventFramwork
{
    /// <summary>
    /// 事件發布器,發布消息
    /// </summary>
    public interface IEventPublisher:IDisposable
    {
        /// <summary>
        /// 事件發布器,發布事件
        /// </summary>
        /// <typeparam name="TEvent"></typeparam>
        /// <param name="event">事件</param>
        /// <param name="cancellationToken">任務取消令牌,取消任務</param>
        /// <returns></returns>
        Task PublishAsync<TEvent>(TEvent @event, CancellationToken cancellationToken = default)
        where TEvent : IEvent;
    }
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace TQF.EventBus.EventFramwork
{
    /// <summary>
    /// 事件訂閱器訂閱消息
    /// </summary>
    public interface IEventSubscriber:IDisposable
    {
        void Subscriber();
    }
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace TQF.EventBus.EventFramwork
{
    /// <summary>
    /// 事件總線接口,定義事件通訊渠道,消息訂閱功能,消息派發功能(消息的路由,過濾,選擇)等。
    /// 通過事件總線管理兩者
    /// </summary>
    public interface IEventBus:IEventPublisher,IEventSubscriber
    {
    }
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace TQF.EventBus.EventFramwork
{
    /// <summary>
    /// 定義事件傳遞的參數
    /// </summary>
    public class EventProcessedEventArgs:EventArgs
    {
        public IEvent Event { get; }

        public EventProcessedEventArgs(IEvent @event)
        {
            this.Event = @event;
        }
    }
}

四、總結

  1、事件總線的目的是對業務的解耦,通過設計合理的架構來達到這個目標,既然是合理的框架,就涉及到存儲、容錯、路由、異步、重試等問題,所以上述提供是一個事件總線雛形。

  2、對於模式和架構,一個模式,一個架構其構成的最小單位可以理解為對象,通過對對象的划分、割裂,單獨成個體,通過關系連接這些個體,建立起一個模型->模式->架構。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM