DDD~领域事件与事件总线

来源:互联网 发布:8051单片机内部结构图 编辑:程序博客网 时间:2024/05/21 10:00
DDD~领域事件与事件总线

回到目录

谈谈它

终于有些眉目了,搜刮了很多牛人的资料,英文的,中文的,民国文的,终于小有成就了,同时也做了个DEMO,领域事件这东西好,但需要你明白它之后才会说好,而对于明白领域事件这件事来说,它的门槛有点高,居然花了我三天的时间才把它搞定,嗨!

占占给它的定义

领域事件:Domain Event,是针对某个业务来说的,或者说针对某个聚合的业务来说的,例如订单生成这种业务,它可以同时对应一种事件,比如叫做OrderGeneratorEvent,而你的零散业务可能随时会变,加一些业务,减一些业务,而对于订单生成这个事件来说,它是唯一不变的,而我们需要把这些由产生订单而发生变化的事情拿出来,而拿出来的这些业务就叫做"领域事件".其中的领域指的就是订单生成这个聚合;而事件指的就是那些零散业务的统称.

它的主要几个抽象

在面向对象的编程世界里,做这种事情我们需要几个抽象:

领域对象事件标示:(标示接口,接口的一种,用来约束一批对象)IEvent

领域对象的处理方法,行为:(需要让那些零散的模块重写的方法,起个听起来熟悉的名字,叫它handle吧)IEventHandler=>Handle

事件总线:事件处理核心类,承载了事件的发布,订阅与取消订阅的逻辑,EventBus

某个领域对象:为了实现某个业务,而创建的实体类,它里面有事件所需要的数据,它继承了IEvent

某个领域对象的事件:它是一个事件处理类,它实现了IEventHandler,它所处理的事情需要在Handle里去完成

我的Demo的实现

一 结果图:

二 核心类:

IEvent接口,标示接口往往都是空的,呵呵

复制代码
    /// <summary>    /// 事件实体基类    /// </summary>    public interface IEvent    {    }
复制代码

IEventHandler接口,只有一个行为方法Handle

复制代码
    /// <summary>    /// 事件处理接口    /// </summary>    /// <typeparam name="TEvent">继承IEvent对象的事件源对象</typeparam>    public interface IEventHandler<TEvent>        where TEvent : IEvent    {        /// <summary>        /// 处理程序        /// </summary>        /// <param name="evt"></param>        void Handle(TEvent evt);    }
复制代码

EventBus是实现事件的核心,在这版里,它支持异步事件机制,使用Task实现,所以它需要运行在.net4.5平台之上

复制代码
   /// <summary>    /// 事件总线    /// 发布与订阅处理逻辑    /// 核心功能代码    /// </summary>    public class EventBus    {        private EventBus() { }        private static EventBus _eventBus = null;        private readonly object sync = new object();        /// <summary>        /// 对于事件数据的存储,目前采用内存字典        /// </summary>        private static Dictionary<Type, List<object>> eventHandlers = new Dictionary<Type, List<object>>();        /// <summary>        // checks if the two event handlers are equal. if the event handler is an action-delegated, just simply        // compare the two with the object.Equals override (since it was overriden by comparing the two delegates. Otherwise,        // the type of the event handler will be used because we don't need to register the same type of the event handler        // more than once for each specific event.        /// </summary>        private readonly Func<object, object, bool> eventHandlerEquals = (o1, o2) =>         {             var o1Type = o1.GetType();             var o2Type = o2.GetType();             if (o1Type.IsGenericType &&                 o1Type.GetGenericTypeDefinition() == typeof(ActionDelegatedEventHandler<>) &&                 o2Type.IsGenericType &&                 o2Type.GetGenericTypeDefinition() == typeof(ActionDelegatedEventHandler<>))                 return o1.Equals(o2);             return o1Type == o2Type;         };        /// <summary>        /// 初始化空的事件总件        /// </summary>        public static EventBus Instance        {            get            {                return _eventBus ?? (_eventBus = new EventBus());            }        }        /// <summary>        /// 通过XML文件初始化事件总线,订阅信自在XML里配置        /// </summary>        /// <returns></returns>        public static EventBus InstanceForXml()        {            if (_eventBus == null)            {                XElement root = XElement.Load(System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "EventBus.xml"));                foreach (var evt in root.Elements("Event"))                {                    List<object> handlers = new List<object>();                    Type publishEventType = Type.GetType(evt.Element("PublishEvent").Value);                    foreach (var subscritedEvt in evt.Elements("SubscribedEvents"))                        foreach (var concreteEvt in subscritedEvt.Elements("SubscribedEvent"))                            handlers.Add(Type.GetType(concreteEvt.Value));                    eventHandlers[publishEventType] = handlers;                }                _eventBus = new EventBus();            }            return _eventBus;        }        #region 事件订阅&取消订阅,可以扩展        /// <summary>        /// 订阅事件列表        /// </summary>        /// <param name="type"></param>        /// <param name="subTypeList"></param>        public void Subscribe<TEvent>(IEventHandler<TEvent> eventHandler)            where TEvent : class, IEvent        {            lock (sync)            {                var eventType = typeof(TEvent);                if (eventHandlers.ContainsKey(eventType))                {                    var handlers = eventHandlers[eventType];                    if (handlers != null)                    {                        if (!handlers.Exists(deh => eventHandlerEquals(deh, eventHandler)))                            handlers.Add(eventHandler);                    }                    else                    {                        handlers = new List<object>();                        handlers.Add(eventHandler);                    }                }                else                    eventHandlers.Add(eventType, new List<object> { eventHandler });            }        }        /// <summary>        /// 订阅事件实体        /// </summary>        /// <param name="type"></param>        /// <param name="subTypeList"></param>        public void Subscribe<TEvent>(Action<TEvent> eventHandlerFunc)            where TEvent : class, IEvent        {            Subscribe<TEvent>(new ActionDelegatedEventHandler<TEvent>(eventHandlerFunc));        }        public void Subscribe<TEvent>(IEnumerable<IEventHandler<TEvent>> eventHandlers)            where TEvent : class, IEvent        {            foreach (var eventHandler in eventHandlers)                Subscribe<TEvent>(eventHandler);        }        /// <summary>        /// 取消订阅事件        /// </summary>        /// <param name="type"></param>        /// <param name="subType"></param>        public void Unsubscribe<TEvent>(IEventHandler<TEvent> eventHandler)            where TEvent : class, IEvent        {            lock (sync)            {                var eventType = typeof(TEvent);                if (eventHandlers.ContainsKey(eventType))                {                    var handlers = eventHandlers[eventType];                    if (handlers != null                        && handlers.Exists(deh => eventHandlerEquals(deh, eventHandler)))                    {                        var handlerToRemove = handlers.First(deh => eventHandlerEquals(deh, eventHandler));                        handlers.Remove(handlerToRemove);                    }                }            }        }        public void Unsubscribe<TEvent>(IEnumerable<IEventHandler<TEvent>> eventHandlers)          where TEvent : class, IEvent        {            foreach (var eventHandler in eventHandlers)                Unsubscribe<TEvent>(eventHandler);        }        public void Unsubscribe<TEvent>(Action<TEvent> eventHandlerFunc)            where TEvent : class, IEvent        {            Unsubscribe<TEvent>(new ActionDelegatedEventHandler<TEvent>(eventHandlerFunc));        }        #endregion        #region 事件发布        /// <summary>        /// 发布事件,支持异步事件        /// </summary>        /// <typeparam name="TEvent"></typeparam>        /// <param name="evnt"></param>        public void Publish<TEvent>(TEvent evnt)           where TEvent : class, IEvent        {            if (evnt == null)                throw new ArgumentNullException("evnt");            var eventType = evnt.GetType();            if (eventHandlers.ContainsKey(eventType)                && eventHandlers[eventType] != null                && eventHandlers[eventType].Count > 0)            {                var handlers = eventHandlers[eventType];                foreach (var handler in handlers)                {                    var eventHandler = handler as IEventHandler<TEvent>;                    if (eventHandler.GetType().IsDefined(typeof(HandlesAsynchronouslyAttribute), false))                    {                        Task.Factory.StartNew((o) => eventHandler.Handle((TEvent)o), evnt);                    }                    else                    {                        eventHandler.Handle(evnt);                    }                }            }        }        public void Publish<TEvent>(TEvent evnt, Action<TEvent, bool, Exception> callback, TimeSpan? timeout = null)           where TEvent : class, IEvent        {            if (evnt == null)                throw new ArgumentNullException("evnt");            var eventType = evnt.GetType();            if (eventHandlers.ContainsKey(eventType) &&                eventHandlers[eventType] != null &&                eventHandlers[eventType].Count > 0)            {                var handlers = eventHandlers[eventType];                List<Task> tasks = new List<Task>();                try                {                    foreach (var handler in handlers)                    {                        var eventHandler = handler as IEventHandler<TEvent>;                        if (eventHandler.GetType().IsDefined(typeof(HandlesAsynchronouslyAttribute), false))                        {                            tasks.Add(Task.Factory.StartNew((o) => eventHandler.Handle((TEvent)o), evnt));                        }                        else                        {                            eventHandler.Handle(evnt);                        }                    }                    if (tasks.Count > 0)                    {                        if (timeout == null)                            Task.WaitAll(tasks.ToArray());                        else                            Task.WaitAll(tasks.ToArray(), timeout.Value);                    }                    callback(evnt, true, null);                }                catch (Exception ex)                {                    callback(evnt, false, ex);                }            }            else                callback(evnt, false, null);        }        #endregion    }
复制代码

一个具体的领域对象,它继承IEvent

复制代码
    /// <summary>    /// 添加订单的事件    /// </summary>    public class OrderGeneratorEvent : IEvent    {        public int OrderID { get; set; }    }
复制代码

一个为OrderGeneratorEvent工作的领域事件,它用来为客户发邮件

复制代码
   /// <summary>    /// 发邮件功能    /// </summary>    public class OrderAddedEventHandler_SendEmail : IEventHandler<OrderGeneratorEvent>    {        public void Handle(OrderGeneratorEvent evt)        {            Console.WriteLine("Order_Number:{0},Send a Email.", evt.OrderID);        }    }
复制代码

下面看一个主程序:

复制代码
   static void Main(string[] args)    {          EventBus.Instance.Subscribe(new OrderAddedEventHandler_SendEmail());            var entity = new OrderGeneratorEvent { OrderID = 1 };            Console.WriteLine("生成一个订单,单号为{0}", entity.OrderID);            EventBus.Instance.Publish(entity);            Console.ReadKey();    }
复制代码

下面是运行结果:

嗨,终于理解这东西了,呵呵,在此感谢一下晴阳兄,它对DDD的贡献非常大...

回到目录


http://www.cnblogs.com/lori/p/3476703.html

原创粉丝点击