中文字幕精品亚洲无线码二区,国产黄a三级三级三级看三级,亚洲七七久久桃花影院,丰满少妇被猛烈进入,国产小视频在线观看网站

DDD~領域事件與(yu)事件總線

回到目錄

談談它

終于(yu)有些眉目(mu)了(le)(le),搜刮了(le)(le)很多牛人的(de)資料(liao),英文的(de),中文的(de),民國文的(de),終于(yu)小有成就了(le)(le),同時(shi)也做了(le)(le)個(ge)DEMO,領(ling)域事件(jian)這東西好(hao),但需要你(ni)明(ming)白(bai)它(ta)(ta)(ta)之后才(cai)會說好(hao),而對(dui)于(yu)明(ming)白(bai)領(ling)域事件(jian)這件(jian)事來說,它(ta)(ta)(ta)的(de)門檻有點高,居然花了(le)(le)我三天(tian)的(de)時(shi)間才(cai)把它(ta)(ta)(ta)搞定,嗨!

占占給它的定義

領域事件(jian):Domain Event,是針(zhen)對(dui)某(mou)個(ge)業務(wu)來說的(de)(de)(de)(de),或者說針(zhen)對(dui)某(mou)個(ge)聚合的(de)(de)(de)(de)業務(wu)來說的(de)(de)(de)(de),例如訂單生成這(zhe)種(zhong)業務(wu),它可(ke)以同時(shi)對(dui)應(ying)一(yi)(yi)種(zhong)事件(jian),比如叫做(zuo)(zuo)OrderGeneratorEvent,而(er)(er)你的(de)(de)(de)(de)零散業務(wu)可(ke)能隨時(shi)會變(bian),加一(yi)(yi)些(xie)業務(wu),減(jian)一(yi)(yi)些(xie)業務(wu),而(er)(er)對(dui)于訂單生成這(zhe)個(ge)事件(jian)來說,它是唯一(yi)(yi)不變(bian)的(de)(de)(de)(de),而(er)(er)我們(men)需要(yao)把這(zhe)些(xie)由(you)產生訂單而(er)(er)發生變(bian)化的(de)(de)(de)(de)事情拿出(chu)來,而(er)(er)拿出(chu)來的(de)(de)(de)(de)這(zhe)些(xie)業務(wu)就叫做(zuo)(zuo)"領域事件(jian)".其中的(de)(de)(de)(de)領域指的(de)(de)(de)(de)就是訂單生成這(zhe)個(ge)聚合;而(er)(er)事件(jian)指的(de)(de)(de)(de)就是那些(xie)零散業務(wu)的(de)(de)(de)(de)統稱.

它的主要幾個抽象

在面(mian)向對象的編程世(shi)界(jie)里,做這種事情我們需(xu)要幾個抽象:

領(ling)域(yu)對(dui)象事件標示:(標示接口,接口的(de)一種,用來(lai)約束一批對(dui)象)IEvent

領域對象的處(chu)理方(fang)法,行為:(需要讓那(nei)些零散的模塊重寫的方(fang)法,起個(ge)聽起來(lai)熟悉的名字(zi),叫它handle吧)IEventHandler=>Handle

事件(jian)總線(xian):事件(jian)處理核(he)心類,承載了事件(jian)的(de)發(fa)布,訂(ding)閱與取(qu)消訂(ding)閱的(de)邏輯,EventBus

某個(ge)領域對象:為了實現某個(ge)業務(wu),而創建的實體(ti)類,它(ta)里面有(you)事件所需(xu)要的數(shu)據,它(ta)繼承了IEvent

某個領(ling)域對象的(de)事件:它(ta)是一個事件處(chu)理類,它(ta)實現了IEventHandler,它(ta)所處(chu)理的(de)事情(qing)需要在Handle里去完成

我的Demo的實現

一 結果圖:

二 核心類:

IEvent接(jie)(jie)口,標示接(jie)(jie)口往(wang)往(wang)都是空的,呵呵

    /// <summary>
    /// 事件實體基類
    /// </summary>
    public interface IEvent
    {
    }

IEventHandler接口,只有一個行為方法Handle

    /// <summary>
    /// 事件處理(li)接口
    /// </summary>
    /// <typeparam name="TEvent">繼承IEvent對象的事件(jian)源對象</typeparam>
    public interface IEventHandler<TEvent>
        where TEvent : IEvent
    {
        /// <summary>
        /// 處理程序
        /// </summary>
        /// <param name="evt"></param>
        void Handle(TEvent evt);

    }

EventBus是(shi)實現(xian)(xian)事件的核心,在這版里(li),它(ta)支持異(yi)步事件機制,使用Task實現(xian)(xian),所以它(ta)需要(yao)運行在.net4.5平臺之上

   /// <summary>
    /// 事件總(zong)線
    /// 發布與訂閱處(chu)理邏輯
    /// 核(he)心(xin)功能代碼
    /// </summary>
    public class EventBus
    {
        private EventBus() { }

        private static EventBus _eventBus = null;
        private readonly object sync = new object();
        /// <summary>
        /// 對于(yu)事件數據的存儲,目前采用內(nei)存字典
        /// </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>
        /// 初始化空的事件(jian)總件(jian)
        /// </summary>
        public static EventBus Instance
        {
            get
            {
                return _eventBus ?? (_eventBus = new EventBus());
            }
        }
        /// <summary>
        /// 通過XML文件初始化事件總線,訂閱(yue)信自在XML里(li)配(pei)置
        /// </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>
        /// 訂閱(yue)事件列(lie)表
        /// </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>
        /// 訂閱事(shi)件實體(ti)
        /// </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>
        /// 取(qu)消訂閱事件(jian)
        /// </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

    }

一個具(ju)體的領域對象(xiang),它繼承IEvent

    /// <summary>
    /// 添加訂單(dan)的事(shi)件
    /// </summary>
    public class OrderGeneratorEvent : IEvent
    {
        public int OrderID { get; set; }
    }

一個為OrderGeneratorEvent工作的領域(yu)事件,它用來為客(ke)戶發郵件

   /// <summary>
    /// 發(fa)郵(you)件功(gong)能(neng)
    /// </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);
      &nbsp;     Console.ReadKey(); }

下面是運行結果:

嗨,終于(yu)理解(jie)這(zhe)東西了,呵呵,在此感謝一下晴陽兄(xiong),它(ta)對DDD的(de)貢(gong)獻非(fei)常(chang)大...

回到目錄

posted @ 2013-12-16 14:21  張占嶺  閱讀(16151)  評論(10)    收藏  舉報