DDD~领域事件应用篇(订单处理变得更清晰)

回到目录html

上一讲主要说了领域事件和领域总线,这并非一个很容易理解的文章,因此本讲实例篇主要是为了补充上一讲的理论知识,本讲实例关注的是实际中的订单处理模块,咱们知道,订单处理是电子商务的核心,每每在这里面,会有不少逻辑,在开发时,给咱们带来了很多的难度,如何更好的分离关注点,是本讲的主题;本讲主要是修改订单状态后,为用户发通知为例,来以此更好的说一下领域事件在实际中的做用。设计模式

前言 领域事件使用的设计模式是发布/订阅模式,或者叫观察者模式。spa

一 订单的几种状态,在订单进入到其中一些状态时,须要通知用户

  public enum OrderStatus
    {
        /// <summary>
        /// 表示销售订单的已建立状态 - 代表销售订单已被建立(未用)。
        /// </summary>
        [Description("用户下单")]
        Created = 0,
        /// <summary>
        /// 订单被用户取消
        /// </summary>
        [Description("取消订单")]
        Canceled,
        /// <summary>
        /// 表示销售订单的已付款状态 - 代表客户已向销售订单付款。
        /// </summary>
        [Description("用户付款")]
        Paid,
        /// <summary>
        /// 表示销售订单的已发货状态。
        /// </summary>
        [Description("已经发货")]
        Dispatched,
        /// <summary>
        /// 订单已经完成
        /// </summary>
        [Description("订单完成")]
        Finished,

    }

二 为须要通知的状态,建立领域事件数据源(原来在.net事件里,它通常是EventArgs对象)

    /// <summary>
    /// 订单已经确认事件源
    /// </summary>
    public class Order_Confirm_Event : Project.Events.EventBase
    {
        public int OrderId { get; set; }
        public string UserName { get; set; }
    }
    /// <summary>
    /// 订单已经付款事件缘
    /// </summary>
    public class Order_Paid_Event : Project.Events.EventBase
    {
        public int OrderId { get; set; }
        public string UserName { get; set; }
        public decimal TotalPrice { get; set; }
    }
    /// <summary>
    /// 订单已经发货事件源
    /// </summary>
    public class Order_Dispatch_Event : Project.Events.EventBase
    {
        public int OrderId { get; set; }
        public string UserName { get; set; }
    }

三 为这些事件源添加事件处理方式

咱们通常理解为“行为”,一种事件源能够有多种事件行为,如一个订单付款事件源,它能够同时有电子邮件行为和短信行为;反之,一个事件处理方式也能够对应多个事件源,如一个电子邮件行为,它能够同时对应订单付款.net

和订单发货等事件源,因此,领域事件在项目中是很是灵活的。设计

    /// <summary>
    /// 发Email的事件处理方式
    /// 调用方法:EventBus.Instance.Subscribe<User_Depts_Event>(new SendEmailEventHandler())
    ///      EventBus.Instance.Subscribe<User_Roles_Event>(new SendEmailEventHandler())
    /// </summary>
    public class SendEmail_EventHandler :
       IEventHandler<Order_Confirm_Event>,
        IEventHandler<Order_Dispatch_Event>,
        IEventHandler<Order_Paid_Event>
    {
        static string prefix = "本消息来自电子邮件";

        #region IEventHandler<Order_Confirm_Event> 成员

        public void Handle(Order_Confirm_Event evt)
        {
            Logger.Core.LoggerFactory.Instance.Logger_Info(string.Format("尊敬的客户{0},你的订单已经确认,订单号{1},请尽快付款!({2})[{3}]"
                , evt.UserName
                , evt.OrderId
                , evt.EventDate
                , prefix));
        }

        #endregion

        #region IEventHandler<Order_Dispatch_Event> 成员

        public void Handle(Order_Dispatch_Event evt)
        {
            Logger.Core.LoggerFactory.Instance.Logger_Info(string.Format("尊敬的客户{0},你的订单已经发货,订单号{1},请注意查收!({2})[{3}]"
                , evt.UserName
                , evt.OrderId
                , evt.EventDate
                , prefix));

        }

        #endregion

        #region IEventHandler<Order_Paid_Event> 成员

        public void Handle(Order_Paid_Event evt)
        {
            Logger.Core.LoggerFactory.Instance.Logger_Info(string.Format("尊敬的客户{0},你的订单已经成功付款,订单号{1},付款金额为{2}元,咱们会尽快安排发货!({3})[{4}]"
                 , evt.UserName
                 , evt.OrderId
                 , evt.TotalPrice
                 , evt.EventDate
                 , prefix));
        }

        #endregion
    }
    /// <summary>
    /// 发短信的事件处理方式
    /// </summary>
    public class SendSMS_EventHandler :
         IEventHandler<Order_Confirm_Event>,
         IEventHandler<Order_Dispatch_Event>,
         IEventHandler<Order_Paid_Event>
    {
        static string prefix = "本消息来自短信";

        #region IEventHandler<Order_Confirm_Event> 成员

        public void Handle(Order_Confirm_Event evt)
        {
            Logger.Core.LoggerFactory.Instance.Logger_Info(string.Format("尊敬的客户{0},你的订单已经确认,订单号{1},请尽快付款!({2})[{3}]"
                , evt.UserName
                , evt.OrderId
                , evt.EventDate
                , prefix));
        }

        #endregion

        #region IEventHandler<Order_Dispatch_Event> 成员

        public void Handle(Order_Dispatch_Event evt)
        {
            Logger.Core.LoggerFactory.Instance.Logger_Info(string.Format("尊敬的客户{0},你的订单已经发货,订单号{1},请注意查收!({2})[{3}]"
                , evt.UserName
                , evt.OrderId
                , evt.EventDate
                , prefix));

        }

        #endregion

        #region IEventHandler<Order_Paid_Event> 成员

        public void Handle(Order_Paid_Event evt)
        {
            Logger.Core.LoggerFactory.Instance.Logger_Info(string.Format("尊敬的客户{0},你的订单已经成功付款,订单号{1},付款金额为{2}元,咱们会尽快安排发货!({3})[{4}]"
                 , evt.UserName
                 , evt.OrderId
                 , evt.TotalPrice
                 , evt.EventDate
                 , prefix));
        }

        #endregion
    }

四 订阅领域事件

咱们须要有一个入口来订阅领域事件,如订阅订单确认事件,订单付款事件等,简单的作法是在global里统一注册,而标准合理的做法,我以为应该在订单controller的静态构造方法里去注册它,由于只有用户操做订单相关模块时,才可能触日志

发订单这些事件!code

     /// <summary>
        /// 类的构造方法,处理与具体实例没法的东西
        /// </summary>
        static OrderController()
        {
            #region 订阅相关领域事件

            #region 订阅发email处理方式
            EventBus.Instance.Subscribe<Order_Confirm_Event>(new SendEmail_EventHandler());
            EventBus.Instance.Subscribe<Order_Dispatch_Event>(new SendEmail_EventHandler());
            EventBus.Instance.Subscribe<Order_Paid_Event>(new SendEmail_EventHandler());
            #endregion

            #region 订阅发短信的处理方式
            EventBus.Instance.Subscribe<Order_Confirm_Event>(new SendSMS_EventHandler());
            EventBus.Instance.Subscribe<Order_Dispatch_Event>(new SendSMS_EventHandler());
            EventBus.Instance.Subscribe<Order_Paid_Event>(new SendSMS_EventHandler());
            #endregion

            #endregion
        }

咱们看到了,每种订单事件源都被注册了电子邮件和短信两种事件处理方式,这在对应的事件被触发(发布,publish)以后,它们会被执行。orm

六 触发具体事件

具体的事件在具体的方法里,独立的去触发,通常它会在业务逻辑层完成htm

     /// <summary>
        /// 用户下单:create
        /// </summary>
        /// <param name="entity"></param>
        public void DoOrder(Order_Info entity)
        {
            entity.OrderStatus = (int)OrderStatus.Created;
            _orderRepository.Insert(entity);
            entity.Order_Detail.ToList().ForEach(j => j.OrderId = entity.Id);
            _orderDetailRepository.Insert(entity.Order_Detail);
            EventBus.Instance.Publish(new Order_Confirm_Event { OrderId = entity.Id, UserName = entity.UserName });
        }

        /// <summary>
        /// 订单付款:paid
        /// </summary>
        /// <param name="entity"></param>
        public void PaidOrder(Order_Info entity)
        {
            entity.OrderStatus = (int)OrderStatus.Paid;
            _orderRepository.Update(entity);
            EventBus.Instance.Publish(new Order_Paid_Event { OrderId = entity.Id, TotalPrice = entity.TotalPrice, UserName = entity.UserName });
        }

        /// <summary>
        /// 订单发货:dispatch
        /// </summary>
        /// <param name="entity"></param>
        public void DispatchOrder(Order_Info entity)
        {
            entity.OrderStatus = (int)OrderStatus.Dispatched;
            _orderRepository.Update(entity);
            EventBus.Instance.Publish(new Order_Dispatch_Event { OrderId = entity.Id, UserName = entity.UserName });
        }

八 最后,咱们看一下处理处理页面和结果的截图对象

生成的日志

生成的日志内容,相似于用户上到的电子邮件或者短信的内容

怎么样,看完这个例子相信您对领域事件有了更清晰的认识了吧,呵呵!

回到目录

相关文章
相关标签/搜索