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

Lind.DDD.Events領域事件介紹

回到目錄

閑話多說

領(ling)域事(shi)件(jian)大(da)叔感覺是最不(bu)好講的(de)一(yi)篇文章,所以拖(tuo)欠了(le)(le)很久,但最終還是在(zai)2015年(nian)年(nian)前(qian)(陰歷)把這(zhe)(zhe)個知識點(dian)講一(yi)下,事(shi)件(jian)這(zhe)(zhe)個東(dong)西早在(zai)C#1.0時(shi)代就有了(le)(le),那時(shi)學起來也是一(yi)個費勁,什(shen)么(me)是委(wei)托,哪個是事(shi)件(jian),搞的(de)大(da)家是糊里糊涂,進入C#2.0時(shi)代后(hou),大(da)叔也買了(le)(le)一(yi)本書(shu),對于delegate和event這(zhe)(zhe)兩個知識點(dian)看了(le)(le)至少有20幾遍,感覺稍微有點(dian)明白了(le)(le),明白了(le)(le)其中的(de)真諦和用意。

委托:方(fang)(fang)法的規范,方(fang)(fang)法的模板,可以代表一類(lei)方(fang)(fang)法的集(ji)合

事(shi)(shi)件(jian):委托(tuo)的實例,事(shi)(shi)件(jian)在(zai)使用之前需要(yao)為它賦值,當然賦的就是一個方法;事(shi)(shi)件(jian)可以注(zhu)冊和(he)取消,當你注(zhu)冊一個事(shi)(shi)件(jian)之后,在(zai)事(shi)(shi)件(jian)被(bei)(bei)觸發(fa)后,被(bei)(bei)注(zhu)冊的方法將會被(bei)(bei)執行(xing),這一般(ban)被(bei)(bei)稱為“方法的回(hui)調”,在(zai)設(she)計模(mo)式(shi)里(li),又被(bei)(bei)稱為“pub/sub模(mo)式(shi)”,即發(fa)布(bu)/訂閱(yue)模(mo)式(shi);在(zai)C#語言發(fa)展過(guo)程中,設(she)計得(de)(de)為程序開發(fa)者考慮的很多,有(you)些寫法得(de)(de)到了精簡,如(ru)Action和(he)Func委托(tuo)的出現之后,我們基本上(shang)告別(bie)了delegate,這對程序開發(fa)人員無疑是一件(jian)好事(shi)(shi)。

大叔框架中的事件

在大(da)叔框架(jia)里(li),事件是常客,比如在早期的(de)(de)(de)倉儲代碼里(li),你可(ke)以(yi)傳遞(di)一個Action<string>的(de)(de)(de)委(wei)(wei)托,來(lai)進(jin)行(xing)日志的(de)(de)(de)記錄,這種方(fang)(fang)法在IoC出(chu)現后,被(bei)大(da)叔屏蔽了(le),原因不在這里(li)說(shuo)了(le),還有(you)就是在N層(ceng)(ceng)架(jia)構里(li),WEB層(ceng)(ceng)與BLL層(ceng)(ceng)進(jin)行(xing)通訊時,WEB層(ceng)(ceng)通過(guo)HttpClient請求第(di)三方(fang)(fang)的(de)(de)(de)API獲取數據,而BLL層(ceng)(ceng)的(de)(de)(de)方(fang)(fang)法需要(yao)用到這個第(di)三方(fang)(fang)API的(de)(de)(de)返回(hui)值(zhi),而在BLL層(ceng)(ceng)直接訪問HTTP顯(xian)然(ran)是不合(he)適(shi)的(de)(de)(de),所以(yi),在WEB層(ceng)(ceng)到BLL層(ceng)(ceng)的(de)(de)(de)方(fang)(fang)法參數設計時,需要(yao)有(you)一個委(wei)(wei)托來(lai)接改從WEB層(ceng)(ceng)回(hui)調(diao)(diao)的(de)(de)(de)方(fang)(fang)法返回(hui)值(zhi),這種代碼一般稱為(wei)“方(fang)(fang)法回(hui)調(diao)(diao)”。

web層向BLL層傳入一個(ge)委(wei)托

  var entity = rechargeService.RechargeAuto(
                        task,
                        beforeTime,
                        out result,
                        (studentid, money) =>
                        {
              //代碼
              });

 

BLL層接(jie)改這(zhe)個委(wei)托的返回(hui)值(zhi),代(dai)碼(ma)在調用bll層這(zhe)個方法(fa)時,首(shou)先會回(hui)調web層的http的方法(fa)

public Task_xuexiba_Recharge RechargeAuto(
         Task_Info task,
         DateTime beforeTime,
         out bool result,
         Func<int, decimal, RechargeXuexibaDTO> api)
        {
      //代碼(ma)
      }
  var apiEntity = api(task.Task_ParametersForXuexibaRecharge.StudentID, task.Task_ParametersForXuexibaRecharge.Money);

Lind.DDD框架里的領域事件

事件源后綴:Event

事件(jian)處(chu)理方法(fa)后(hou)綴:EventHandler

領域事件(jian)(jian)(jian)一般出(chu)現個領域實(shi)體里(li),在(zai)實(shi)體被建立時(shi),會(hui)訂(ding)閱和(he)(he)自己有(you)關的事件(jian)(jian)(jian),每個事件(jian)(jian)(jian)都(dou)有(you)一個或(huo)者多(duo)個事件(jian)(jian)(jian)處(chu)理方法(fa),事件(jian)(jian)(jian)處(chu)理方法(fa)可以進(jin)行(xing)數據庫操(cao)(cao)作(zuo),或(huo)者網絡和(he)(he)文件(jian)(jian)(jian)的操(cao)(cao)作(zuo),如發(fa)通知,寫文件(jian)(jian)(jian)等,所以有(you)時(shi)候(hou)我們的事件(jian)(jian)(jian)需要設計成異步(bu)的事件(jian)(jian)(jian)。

程序中的事件事件

  #region 領域模型
    public class Order
    {
        public Order()
        {
            Lind.DDD.Events.EventBus.Instance.Subscribe(new OrderInsertEventHandler());
            Lind.DDD.Events.EventBus.Instance.Subscribe<OrderPaid>(new OrderUpdateEventHandler());
        }

        public System.Guid Id { get; set; }
        public System.Guid UserId { get; set; }
        public string UserName { get; set; }
        public decimal TotalFee { get; set; }

        /// <summary>
        /// 用戶提交并確認訂單
        /// </summary>
        public void ComfirmOrder()
        {
            //事(shi)件發(fa)布
            Lind.DDD.Events.EventBus.Instance.Publish(new OrderConfirm
            {
                TotalFee = TotalFee,
                UserName = UserName,
                UserId = UserId,
            });
        }

    }

    #endregion

下面是領域事件源

   /// <summary>
    /// 訂單被確認的(de)事件源
    /// </summary>
    public class OrderConfirm : Lind.DDD.Events.IEvent
    {
        public override string ToString()
        {
            return "訂單已(yi)經確認(ren)";
        }
        /// <summary>
        /// 訂單(dan)總(zong)金額(e)
        /// </summary>
        public decimal TotalFee { get; set; }
        /// <summary>
        /// 購買者ID
        /// </summary>
        public Guid UserId { get; set; }
        /// <summary>
        /// 購(gou)買者(zhe)
        /// </summary>
        public string UserName { get; set; }

        #region IEvent 成員

        public Guid AggregateRoot
        {
            get { throw new NotImplementedException(); }
        }

        #endregion
    }

下面是領(ling)域事件的處理程序

   /// <summary>
    /// 訂單(dan)被插(cha)入時的處理(li)程序
    /// </summary>
    public class OrderInsertEventHandler :
          Lind.DDD.Events.IEventHandler<Events.OrderConfirm>
    {
        #region IEventHandler<OrderSigned> 成員

        public void Handle(Events.OrderConfirm evt)
        {
            //處理訂單確(que)認的邏輯
            var orderRepository = new Lind.DDD.Repositories.EF.EFRepository<Orders>();
            orderRepository.SetDataContext(new testEntities());
            orderRepository.Insert(new Orders
            {
                Id = Guid.NewGuid(),
                OrderStatus = 1,
                TotalFee = evt.TotalFee,
                UserId = evt.UserId,
                UserName = evt.UserName,
            });
        }

        #endregion
    }

如果(guo)希望將自己的(de)事件處理程(cheng)序設計成(cheng)異常的(de),即不阻(zu)塞當前(qian)線程(cheng)的(de),可以(yi)讓它添加HandlesAsynchronouslyAttribute這個特(te)性(xing),如下(xia)面這個發送Email的(de)處理程(cheng)序就是一個異步的(de)。

  /// <summary>
    /// 發郵件(jian)功(gong)能[某個(ge)事件(jian)的行為(wei)]
    /// </summary>
    [HandlesAsynchronouslyAttribute]
    public class SendEmailEventHandler :
        IEventHandler<OrderEvent>,
        IEventHandler<UserEvent>
    {

        #region IEventHandler<OrderEvent> 成員

        public void Handle(OrderEvent evt)
        {
            Console.WriteLine("生成和(he)確認訂單(dan){0}時發Email", evt.OrderId);
        }

        #endregion

        #region IEventHandler<UserEvent> 成員

        public void Handle(UserEvent evt)
        {
            Console.WriteLine("建立用戶(hu)后發Email,用戶(hu)ID{0}", evt.UserId);
        }

        #endregion
    }

 全局注冊所有事件處理程序

這(zhe)個是(shi)看完ABP之后(hou)的(de)(de)(de)想法,原理(li)(li)是(shi)把BIN下所(suo)有繼承(cheng)了IEventHandler的(de)(de)(de)類都自(zi)動注冊到事件總線(xian)中,然(ran)后(hou)在事件被觸發后(hou),就自(zi)動執行你(ni)訂閱(yue)的(de)(de)(de)方法了,在項目開發過程(cheng)(cheng)中,推薦使(shi)用(yong)這(zhe)種方法,但需要注意(yi)的(de)(de)(de)是(shi),你(ni)的(de)(de)(de)事件處(chu)理(li)(li)程(cheng)(cheng)序必(bi)須是(shi)顯示定(ding)義的(de)(de)(de),不能使(shi)用(yong)匿(ni)名的(de)(de)(de)處(chu)理(li)(li)程(cheng)(cheng)序.

     /// <summary>
        /// 全局統(tong)一注冊所有(you)事件處理(li)程序,實現了IEventHandlers的
        /// </summary>
        public void SubscribeAll()
        {
            var types = AppDomain.CurrentDomain.GetAssemblies()
                   .SelectMany(a => a.GetTypes()
                   .Where(t => t.GetInterfaces().Contains(typeof(IEventHandlers))))
                   .Where(i => !Excepts.Contains(i.Name))
                   .ToArray();

            foreach (var item in types)
            {
                if (!item.ContainsGenericParameters)
                {
                    var en = Activator.CreateInstance(item);
                    foreach (var t in item.GetInterfaces().Where(i => i.Name != "IEventHandlers"))
                    {
                        Subscribe(t, en);
                    }
                }
            }
        }

 

感謝各位的閱讀!

回到目錄

posted @ 2016-01-29 14:36  張占嶺  閱讀(3927)  評論(3)    收藏  舉報