距離上一篇DDD系列完結已經過了很長一段時間,項目也擱置了一段時間,想想還是繼續完善下去。
DDD領域驅動之干貨(三)完結篇!
上一篇說到了如何實現uow配合Repository在autofac和automapper下實現的功能,今天完善一下事件驅動也就是領域驅動。
領域驅動的概念網上一搜一大推,我就不一一累贅,本文主要講解如何實現領域事件和事件總線。
事件一共提供三個方法去完成事件的實現-----------注冊事件、卸載事件、發布事件
那么在注冊事件的時候我們怎么樣是定義一個事件呢?
如下圖:
圖中的Events為事件,handler為事件的處理,bus為事件總線。
這么一來思路就清晰多了。
首先我們為事件定義一個標識事件的接口。
public interface IEvent { // 獲取產生事件的時間 DateTime Time { get; set; } //事件源 object Source { get; set; } }
所有的事件類都應該實現該接口。
public class Event : IEvent { public DateTime Time { get; set; } public object Source { get; set; } public Event() { Time = DateTime.Now; } }
可以把這個Event看過是domianEvent的根事件,所有的領域事件應該繼承根事件。
public class UserEvent :Event { public User info { get; set; } }
事件我們寫完了,接下來是需要寫事件要執行的處理。
/// <summary> /// 標志接口 /// </summary> public interface IHandler { } /// <summary> /// 事件處理器接口,所有事件處理器都要實現該接口。 /// </summary> public interface IEventHandler<TEvent> : IHandler where TEvent:IEvent { // 處理給定的事件 void Handle(TEvent Event); }
然后是寫一個委托事件處理器。
public class ActionHandler<TEvent> : IEventHandler<TEvent> where TEvent : IEvent { public Action<TEvent> Action { get; private set; } public ActionHandler() { } public ActionHandler(Action<TEvent> handler) { Action = handler; } public void Handle(TEvent Event) { throw new NotImplementedException(); } }
處理事件的方法定義完成后,我們需要完成領域的處理。
public class UserHandler :IEventHandler<UserEvent> { public void Handle(UserEvent Event) { Event.Source = Event.info; } }
所有的事件我們定義完成后,接下來就是事件總線出場了。

public interface IEventBus { //注冊事件 void RegisterAllHandler(IEnumerable<Assembly> assembles); void Register<THandle>(IHandler handle); void Register(Type eventType, Type handler); void Register<THandle>(Action<THandle> action) where THandle : IEvent; //反注冊事件 void UnRegisiter<THandle>(Type handleType) where THandle : IEvent; void UnRegisterAllHandler<THandle>(); //觸發事件 void TiggerEvent<THandle>(THandle eventData) where THandle : IEvent; void TiggerEvent<THandle>(Type eventHandlerType, THandle eventData) where THandle : IEvent; Task TiggerEventAsync<THandle>(THandle eventData) where THandle : IEvent; Task TiggerEventAsycn<THandle>(Type eventHandlerType, THandle eventData) where THandle : IEvent; }
接口定義好了之后是實現接口。

using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using KuRuMi.Mio.DoMain.Events.Events; using KuRuMi.Mio.DoMain.Events.Handler; using System.Reflection; using System.Collections.Concurrent; namespace KuRuMi.Mio.DoMain.Events.Bus { /// <summary> /// 事件總線 /// </summary> public class EventBus : IEventBus { private object locker = new object(); public static EventBus bus => new EventBus(); private static IEnumerable<Assembly> assemly { get; set; } private static readonly ConcurrentDictionary<Type, List<Type>> EventMapping = new ConcurrentDictionary<Type, List<Type>>(); /// <summary> /// 注冊所有事件 /// </summary> /// <param name="assembles"></param> public void RegisterAllHandler(IEnumerable<Assembly> assembles) { assemly = assembles; foreach (Assembly assembly in assembles) { Type[] types = assembly.GetTypes(); foreach (Type type in types) { Type handlerInterfaceType = type.GetInterface("IEventHandler`1"); if (handlerInterfaceType != null) { Type eventType = handlerInterfaceType.GetGenericArguments()[0]; if (!EventMapping.Keys.Contains(eventType)) { Register(eventType, type); } } } } } /// <summary> /// 注冊到事件總線 /// </summary> /// <param name="eventType"></param> /// <returns></returns> private List<Type> GetOrCreateHandlers(Type eventType) { return EventMapping.GetOrAdd(eventType, (type) => new List<Type>()); } #region 注冊事件 /// <summary> /// 手動綁定事件 /// </summary> /// <typeparam name="THandle"></typeparam> /// <param name="handle"></param> public void Register<THandle>(IHandler handle) { Register(typeof(THandle), handle.GetType()); } public void Register(Type eventType, Type handler) { lock (locker) { GetOrCreateHandlers(eventType).Add(handler); } } /// <summary> /// 通過委托注冊 /// </summary> /// <typeparam name="THandle"></typeparam> /// <param name="action"></param> public void Register<THandle>(Action<THandle> action) where THandle : IEvent { ActionHandler<THandle> ActionHandler = new ActionHandler<THandle>(action); Register<THandle>(ActionHandler); } #endregion #region 卸載事件 /// <summary> /// 手動卸載單個事件 /// </summary> /// <typeparam name="THandle"></typeparam> /// <param name="handleType"></param> public void UnRegisiter<THandle>(Type handleType) where THandle : IEvent { lock (locker) { GetOrCreateHandlers(typeof(THandle)).RemoveAll(t => t == handleType); } } /// <summary> /// 卸載所有事件 /// </summary> /// <typeparam name="THandle"></typeparam> public void UnRegisterAllHandler<THandle>() { lock (locker) { GetOrCreateHandlers(typeof(THandle)).Clear(); } } #endregion #region 觸發事件 /// <summary> /// 根據事件源觸發事件 /// </summary> /// <typeparam name="THandle"></typeparam> /// <param name="eventData"></param> public void TiggerEvent<THandle>(THandle eventData) where THandle : IEvent { //獲取所有的事件處理 List<Type> handlerTypes = GetOrCreateHandlers(typeof(THandle)); if (handlerTypes != null && handlerTypes.Count > 0) { foreach (var handlerType in handlerTypes) { var handlerInterface = handlerType.GetInterface("IEventHandler`1"); foreach (Assembly assembly in assemly) { Type[] types = assembly.GetTypes(); foreach (Type type in types) { Type handlerInterfaceType = type.GetInterface("IEventHandler`1"); if (handlerInterfaceType != null) { //判斷兩個類型是否相等 if (handlerInterface == handlerInterfaceType) { var eventType = handlerInterfaceType.GenericTypeArguments[0]; EventMapping[eventType].ForEach(s=> { var obj = Activator.CreateInstance(s) as IEventHandler<THandle>; obj?.Handle(eventData); }); } } } } } } } /// <summary> /// 指定handler觸發事件 /// </summary> /// <typeparam name="THandle"></typeparam> /// <param name="eventData"></param> /// <returns></returns> public void TiggerEvent<THandle>(Type eventHandlerType, THandle eventData) where THandle : IEvent { var handlerInterface = eventHandlerType.GetInterface("IEventHandler`1"); foreach (Assembly assembly in assemly) { Type[] types = assembly.GetTypes(); foreach (Type type in types) { Type handlerInterfaceType = type.GetInterface("IEventHandler`1"); if (handlerInterfaceType != null) { //判斷兩個類型是否相等 if (handlerInterface == handlerInterfaceType) { var eventType = handlerInterfaceType.GenericTypeArguments[0]; EventMapping[eventType].ForEach(s => { var obj = Activator.CreateInstance(s) as IEventHandler<THandle>; obj?.Handle(eventData); }); } } } } } /// <summary> /// 根據事件源觸發事件(異步) /// </summary> /// <typeparam name="THandle"></typeparam> /// <param name="eventData"></param> /// <returns></returns> public Task TiggerEventAsync<THandle>(THandle eventData) where THandle : IEvent { return Task.Run(() => TiggerEvent<THandle>(eventData)); } /// <summary> /// 指定handler觸發事件(異步) /// </summary> /// <typeparam name="THandle"></typeparam> /// <param name="eventHandlerType"></param> /// <param name="eventData"></param> /// <returns></returns> public Task TiggerEventAsycn<THandle>(Type eventHandlerType, THandle eventData) where THandle : IEvent { return Task.Run(() => TiggerEvent<THandle>(eventHandlerType, eventData)); } #endregion } }
代碼上我都有注釋,過多了我就不多做說明。
以上就是我對領域事件和領域總線的理解,歡迎大佬指正。