Lind.DDD.Events领域事件介绍

回到目录

闲话多说

领域事件大叔感觉是最不好讲的一篇文章,所以拖欠了很久,但最终还是在2015年年前(阴历)把这个知识点讲一下,事件这个东西早在C#1.0时代就有了,那时学起来也是一个费劲,什么是委托,哪个是事件,搞的大家是糊里糊涂,进入C#2.0时代后,大叔也买了一本书,对于delegate和event这两个知识点看了至少有20几遍,感觉稍微有点明白了,明白了其中的真谛和用意。

委托:方法的规范,方法的模板,可以代表一类方法的集合

事件:委托的实例,事件在使用之前需要为它赋值,当然赋的就是一个方法;事件可以注册和取消,当你注册一个事件之后,在事件被触发后,被注册的方法将会被执行,这一般被称为“方法的回调”,在设计模式里,又被称为“pub/sub模式”,即发布/订阅模式;在C#语言发展过程中,设计得为程序开发者考虑的很多,有些写法得到了精简,如Action和Func委托的出现之后,我们基本上告别了delegate,这对程序开发人员无疑是一件好事。

大叔框架中的事件

在大叔框架里,事件是常客,比如在早期的仓储代码里,你可以传递一个Action<string>的委托,来进行日志的记录,这种方法在IoC出现后,被大叔屏蔽了,原因不在这里说了,还有就是在N层架构里,WEB层与BLL层进行通讯时,WEB层通过HttpClient请求第三方的API获取数据,而BLL层的方法需要用到这个第三方API的返回值,而在BLL层直接访问HTTP显然是不合适的,所以,在WEB层到BLL层的方法参数设计时,需要有一个委托来接改从WEB层回调的方法返回值,这种代码一般称为“方法回调”。

web层向BLL层传入一个委托

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

BLL层接改这个委托的返回值,代码在调用bll层这个方法时,首先会回调web层的http的方法

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

Lind.DDD框架里的领域事件

事件源后缀:Event

事件处理方法后缀:EventHandler

领域事件一般出现个领域实体里,在实体被建立时,会订阅和自己有关的事件,每个事件都有一个或者多个事件处理方法,事件处理方法可以进行数据库操作,或者网络和文件的操作,如发通知,写文件等,所以有时候我们的事件需要设计成异步的事件。

程序中的事件事件

  #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()
        {
            //事件发布
            Lind.DDD.Events.EventBus.Instance.Publish(new OrderConfirm
            {
                TotalFee = TotalFee,
                UserName = UserName,
                UserId = UserId,
            });
        }

    }

    #endregion

下面是领域事件源

   /// <summary>
    /// 订单被确认的事件源
    /// </summary>
    public class OrderConfirm : Lind.DDD.Events.IEvent
    {
        public override string ToString()
        {
            return "订单已经确认";
        }
        /// <summary>
        /// 订单总金额
        /// </summary>
        public decimal TotalFee { get; set; }
        /// <summary>
        /// 购买者ID
        /// </summary>
        public Guid UserId { get; set; }
        /// <summary>
        /// 购买者
        /// </summary>
        public string UserName { get; set; }

        #region IEvent 成员

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

        #endregion
    }

下面是领域事件的处理程序

   /// <summary>
    /// 订单被插入时的处理程序
    /// </summary>
    public class OrderInsertEventHandler :
          Lind.DDD.Events.IEventHandler<Events.OrderConfirm>
    {
        #region IEventHandler<OrderSigned> 成员

        public void Handle(Events.OrderConfirm evt)
        {
            //处理訂單确认的逻辑
            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
    }

如果希望将自己的事件处理程序设计成异常的,即不阻塞当前线程的,可以让它添加HandlesAsynchronouslyAttribute这个特性,如下面这个发送Email的处理程序就是一个异步的。

  /// <summary>
    /// 发邮件功能[某个事件的行为]
    /// </summary>
    [HandlesAsynchronouslyAttribute]
    public class SendEmailEventHandler :
        IEventHandler<OrderEvent>,
        IEventHandler<UserEvent>
    {

        #region IEventHandler<OrderEvent> 成员

        public void Handle(OrderEvent evt)
        {
            Console.WriteLine("生成和确认订单{0}时发Email", evt.OrderId);
        }

        #endregion

        #region IEventHandler<UserEvent> 成员

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

        #endregion
    }

感谢各位的阅读!

回到目录

时间: 2024-10-26 01:41:24

Lind.DDD.Events领域事件介绍的相关文章

Lind.DDD敏捷领域驱动框架~介绍

最近觉得自己的框架过于复杂,在实现开发使用中有些不爽,自己的朋友们也经常和我说,框架太麻烦了,要引用的类库太多:之前架构之所以这样设计,完全出于对职责分离和代码附复用的考虑,主要参考了微软的DDD大作<N_LayerAPP>这个项目,而在这几年的项目开发用,也尝到了这种职责分享框架的甜头,但在最近的开发中,也看到了其它框架的出现,如<ABP>项目,它主张简单框架,敏捷开发,在项目引用上将核心类库和持久层进行抽象分离,复用在各位领域项目之中,这在项目整个感觉上更加简单,也更容易被人们

Lind.DDD敏捷领域驱动框架~Lind.DDD各层介绍

回到目录 Lind.DDD项目主要面向敏捷,快速开发,领域驱动等,对于它的分层也是能合并的合并,比之前大叔的框架分层更粗糙一些,或者说更大胆一些,在开发人员使用上,可能会感觉更方便了,更益使用了,这就是大叔开发Lind.DDD框架的目的,让一切变得更简单... Lind.DDD层 主要是公用方法,组件,规约等,如日志组件(Logger),消息组件(Messaging),IOC,AOP,缓存(Caching),异常,请求/响应,用户授权(Authorization),安全校验,领域模型(Domai

Lind.DDD.Repositories.Redis层介绍

回到目录 之前已经发生了 大叔之前介绍过关于redis的文章,有缓存,队列,分布式pub/sub,数据集缓存以及仓储redis的实现等等,而今天在Lind.DDD的持久化组件里,redis当然也有一席之地,作为当今最红的key/value存储机制,它在nosql的阵营中发挥着无可代替的作用! 下面是redis文章系列的目录,大家可以进行参考,看目录 Redis学习笔记~Redis在windows环境下的安装 Redis学习笔记~Redis在.net中的应用 Redis学习笔记~Redis提供的五

Lind.DDD.Paging分页模块介绍

回到目录 分页组件网上有很多,MVC.Pager,JSPager等,通过实现方式大体分为前端分页和后端分页,前端分页是前台对list内存本地集合进行分页,缺点就是在大数据情况下,内存占用过高:后端分页就是UI把要返回的页号告诉后台,由后台组织数据并返回,这种方法就是我们经常看到的了:而根据后台集合种类又可以分类List和IQueryable,前者是本地集合,在返回数据时,直接把第几页共几条的集合返回:IQueryable是预查询集合,它是Linq的产物,在很多地里它不通用,除非你的ORM框架支持

Lind.DDD.Repositories.EF层介绍

回到目录 Lind.DDD.Repositories.EF以下简称Repositories.EF,之所以把它从Lind.DDD中拿出来,完全出于可插拔的考虑,让大家都能休会到IoC的魅力,用到哪种方法持久化,就将那个DLL放到应用程序中,完全不需要把所有持久化方式耦合到一个项目里,这也是遵循了OCP的原则,对扩展是开放的,即你可以添加其它的持久化方式,在新的项目里:而不要在原有的项目中进行代码的修改. Repositories.EF做为数据持久化的一种方式,它直接继承了Lind.DDD.IRep

Lind.DDD.Authorization用户授权介绍

回到目录 Lind.DDD.Authorization是Lind.DDD框架的组成部分,之所以把它封装到框架里,原因就是它的通用性,几乎在任何一个系统中,都少不了用户授权功能,用户授权对于任何一个系统来说都是必要的,像管理型的页面都需要用户先去登陆,然后拿到凭证,才可以进行访问,这在MVC和WebApi体系结构里是很容易实现的,像过滤器里的AuthorizeAttribute和ActionFilterAttribute都可以实现用户授权的功能. AuthorizeAttribute和Action

Lind.DDD.Repositories.Mongo层介绍

回到目录 之前已经发生了 大叔之前讲过被仓储化了的Mongodb,而在大叔开发了Lind.DDD之后,决定把这个东西再搬到本框架的仓储层来,这也是大势所趋的,毕竟mongodb是最像关系数据库的NoSql,它的使用场景是其它nosql所不能及的,这点是毋庸置疑的! 下面是大叔总结的Mongodb文章目录,选自<大叔Mongodb系列> MongoDB学习笔记~环境搭建 (2015-03-30 10:34) MongoDB学习笔记~MongoDBRepository仓储的实现 (2015-04-

Lind.DDD.Domain领域模型介绍

回到目录 Lind.DDD.Domain位于Lind.DDD核心项目中,它主要面向领域实体而设计,由一个IEntity的标识接口,EntityBase基类和N个Entity实体类组成,其中IEntity主要用来标识,在仓储操作时,用它来表明操作的实体范围和约束:EntityBase定义了几个公用的属性,为了避免代码的重复,特意将状态,插入时间和更新时间定义到了EntityBase里,而为何不将主键定义进来呢,主要考虑到主键的类型是为确实的,还有就是不同类型的主键可能需要实现不同的特性,如Mong

Lind.DDD.Messaging框架通讯组件介绍

回到目录 大家好,今天有时间来介绍一下Lind.DDD框架里的消息机制,消息发送这块一般的实现方法是将Email,SMS等集成到一个公用类库里,而本身Email和SMS没什么关系,它们也不会有什么接口约定,即你想实现某种消息的多态发送,不需要程序代码,基本不可能实现,而在Lind.DDD里面,大叔将它进行了抽象,消息有自己的统一接口,而对于email和sms只是一种实现而以,这样,就可以发挥面向对象的特性,在sms,email甚至是rtx上进行消息的灵活切换了,说到这样,您心动了吧! Lind.