距離上一篇DDD系列完結已通過了很長一段時間,項目也擱置了一段時間,想一想仍是繼續完善下去。html
上一篇說到了如何實現uow配合Repository在autofac和automapper下實現的功能,今天完善一下事件驅動也就是領域驅動。app
領域驅動的概念網上一搜一大推,我就不一一累贅,本文主要講解如何實現領域事件和事件總線。dom
事件一共提供三個方法去完成事件的實現-----------註冊事件、卸載事件、發佈事件異步
那麼在註冊事件的時候咱們怎麼樣是定義一個事件呢?ide
以下圖:post
圖中的Events爲事件,handler爲事件的處理,bus爲事件總線。url
這麼一來思路就清晰多了。spa
首先咱們爲事件定義一個標識事件的接口。3d
public interface IEvent { // 獲取產生事件的時間 DateTime Time { get; set; } //事件源 object Source { get; set; } }
全部的事件類都應該實現該接口。code
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 } }
代碼上我都有註釋,過多了我就很少作說明。
以上就是我對領域事件和領域總線的理解,歡迎大佬指正。