首页 > 代码库 > DDD领域驱动之干货(四)补充篇!

DDD领域驱动之干货(四)补充篇!

距离上一篇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;
    }
View Code

接口定义好了之后是实现接口。

技术分享
        
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
    }
}
View Code

代码上我都有注释,过多了我就不多做说明。

技术分享

以上就是我对领域事件和领域总线的理解,欢迎大佬指正。

DDD领域驱动之干货(四)补充篇!