静态类DomainEvents:

public static class DomainEvents
    {
        [ThreadStatic]
        private static List<Delegate> _actions;
        private static List<Delegate> Actions
        {
            get
            {
                if (_actions == null)
                {
                    _actions = new List<Delegate>();
                }
                return _actions;
            }
        }

        public static IDisposable Register<T>(Action<T> callback)
        {
            Actions.Add(callback);
            return new DomainEventRegistrationRemover(
                () => Actions.Remove(callback)
                );
        }

        public static void Raise<T>(T eventArgs)
        {
            foreach(Delegate action in Actions)
            {
                (action as Action<T>)?.Invoke(eventArgs);
            }
        }

        private sealed class DomainEventRegistrationRemover : IDisposable
        {
            private readonly Action _callOnDispose;

            public DomainEventRegistrationRemover(Action toCall)
            {
                _callOnDispose = toCall;
            }

            public void Dispose()
            {
                _callOnDispose();
            }
        }
    }

实体OrderForDelivery:

public class OrderForDelivery
    {
        public Guid OrderId { get; set; }
        public FoodDeliveryOrderSteps Status { get; set; }
        public DateTime TimeThatPizzaWasDeliverd { get; set; }
        public DateTime TimeOfOrderBeingPlaced { get; set; }

        //public delegate void DeliveryGuaranteeFailedHandler(DeliveryGuaranteeFailed evnt);
        //public event DeliveryGuaranteeFailedHandler DeliveryGuaranteeFailed;

        public void ConfirmReceipt(DateTime timeThatPizzaWasDelivered)
        {
            if(Status!=FoodDeliveryOrderSteps.Delivered)
            {
                TimeThatPizzaWasDeliverd = timeThatPizzaWasDelivered;
                Status = FoodDeliveryOrderSteps.Delivered;
                if(DeliveryGuaranteeOffer.IsNotSatisfiedBy(TimeOfOrderBeingPlaced,TimeThatPizzaWasDeliverd))
                {
                    DomainEvents.Raise(new DeliveryGuaranteeFailed(this));
                }
            }
        }
    }

仓储MyOrderRepository:

public class MyOrderRepository : IOrderRepository
    {
        private List<OrderForDelivery> orderList=new List<OrderForDelivery>();
        public void AddOrder(OrderForDelivery order)
        {
            orderList.Add(order);
        }
        public OrderForDelivery FindBy(Guid orderId)
        {
            return orderList.SingleOrDefault(x => x.OrderId == orderId);
        }
    }

仓储接口IOrderRepository:

public interface IOrderRepository
    {
        OrderForDelivery FindBy(Guid orderId);
    }

领域服务ConfirmDeliveryOfOrder:

public class ConfirmDeliveryOfOrder
    {
        private IOrderRepository orderRepository;
        public ConfirmDeliveryOfOrder(IOrderRepository repo)
        {
            this.orderRepository = repo;
        }
        public void Confirm(DateTime timeThatPizzaWasDelivered,Guid orderId)
        {
            using (DomainEvents.Register<DeliveryGuaranteeFailed>(onDeliveryFailure))
            {
                var order = orderRepository.FindBy(orderId);
                order.ConfirmReceipt(timeThatPizzaWasDelivered);
            }
        }

        private void onDeliveryFailure(DeliveryGuaranteeFailed evnt)
        {
            Console.WriteLine("送餐超时了...");
        }
    }

错误定义DeliveryGuaranteeFailed:

public class DeliveryGuaranteeFailed
    {
        public DeliveryGuaranteeFailed(OrderForDelivery order)
        {
            this.Order = order;
        }
        public OrderForDelivery Order { get; private set; }
    }

状态枚举FoodDeliveryOrderSteps:

public enum FoodDeliveryOrderSteps
    {
        UnDeliver,
        Delivered
    }

条件判断DeliveryGuaranteeOffer:

public class DeliveryGuaranteeOffer
    {
        public static bool IsNotSatisfiedBy(DateTime timeOfOrderBeingPlaced, DateTime timeThatPizzaWasDeliverd)
        {
            return timeOfOrderBeingPlaced < timeThatPizzaWasDeliverd;
        }
    }

应用层Main():

static void Main(string[] args)
        {
            OrderForDelivery order = new OrderForDelivery()
            {
                OrderId = Guid.NewGuid(),
                Status = FoodDeliveryOrderSteps.UnDeliver,
                TimeOfOrderBeingPlaced = , , , , , )
            };
            MyOrderRepository repo = new MyOrderRepository();
            repo.AddOrder(order);
            ConfirmDeliveryOfOrder confirm = new ConfirmDeliveryOfOrder(repo);
            confirm.Confirm(, , , , , ), order.OrderId);
            Console.ReadKey();
        }

不使用DomainEvents:

public class OrderForDelivery
    {
        public Guid OrderId { get; set; }
        public FoodDeliveryOrderSteps Status { get; set; }
        public DateTime TimeThatPizzaWasDeliverd { get; set; }
        public DateTime TimeOfOrderBeingPlaced { get; set; }

        public delegate void DeliveryGuaranteeFailedHandler(DeliveryGuaranteeFailed evnt);
        public event DeliveryGuaranteeFailedHandler DeliveryGuaranteeFailed;

        public void ConfirmReceipt(DateTime timeThatPizzaWasDelivered)
        {
            if(Status!=FoodDeliveryOrderSteps.Delivered)
            {
                TimeThatPizzaWasDeliverd = timeThatPizzaWasDelivered;
                Status = FoodDeliveryOrderSteps.Delivered;
                if(DeliveryGuaranteeOffer.IsNotSatisfiedBy(TimeOfOrderBeingPlaced,TimeThatPizzaWasDeliverd))
                {
                    //DomainEvents.Raise(new DeliveryGuaranteeFailed(this));
                    DeliveryGuaranteeFailed(new DomainService.DeliveryGuaranteeFailed(this));
                }
            }
        }
public class ConfirmDeliveryOfOrder
    {
        private IOrderRepository orderRepository;
        public ConfirmDeliveryOfOrder(IOrderRepository repo)
        {
            this.orderRepository = repo;
        }
        public void Confirm(DateTime timeThatPizzaWasDelivered,Guid orderId)
        {
            var order = orderRepository.FindBy(orderId);
            order.DeliveryGuaranteeFailed += onDeliveryFailure;
            order.ConfirmReceipt(timeThatPizzaWasDelivered);
            //using (DomainEvents.Register<DeliveryGuaranteeFailed>(onDeliveryFailure))
            //{
            //    var order = orderRepository.FindBy(orderId);
            //    order.ConfirmReceipt(timeThatPizzaWasDelivered);
            //}
        }

        private void onDeliveryFailure(DeliveryGuaranteeFailed evnt)
        {
            Console.WriteLine("送餐超时了...");
        }
    }

领域事件DomainEvents的更多相关文章

  1. ABP框架 - 领域事件(EventBus)

    文档目录 本节内容: EventBus 注入 IEventBus 获取默认实例 定义事件 预定义事件 处理完异常 实体修改 触发事件 处理事件 处理基类事件 处理程序异常 处理多个事件 处理程序注册 ...

  2. 如何一步一步用DDD设计一个电商网站(十三)—— 领域事件扩展

    阅读目录 前言 回顾 本地的一致性 领域事件发布出现异常 订阅者处理出现异常 结语 一.前言 上篇中我们初步运用了领域事件,其中还有一些问题我们没有解决,所以实现是不健壮的,下面先来回顾一下. 二.回 ...

  3. DDD领域驱动设计:领域事件

    1 前置阅读 在阅读本文章之前,你可以先阅读: DDD领域驱动设计是什么 DDD领域驱动设计:实体.值对象.聚合根 DDD领域驱动设计:仓储 MediatR一个优秀的.NET中介者框架 2 什么是领域 ...

  4. 重新整理 .net core 实践篇—————领域事件[二十九]

    前文 前面整理了仓储层,工作单元模式,同时简单介绍了一下mediator. 那么就mediator在看下领域事件启到了什么作用吧. 正文 这里先注册一下MediatR服务: // 注册中间者:Medi ...

  5. ABP(现代ASP.NET样板开发框架)系列之14、ABP领域层——领域事件(Domain events)

    点这里进入ABP系列文章总目录 基于DDD的现代ASP.NET开发框架--ABP系列之14.ABP领域层——领域事件(Domain events) ABP是“ASP.NET Boilerplate P ...

  6. ABP理论学习之事件总线和领域事件

    返回总目录 本篇目录 事件总线 定义事件 触发事件 处理事件 句柄注册 取消注册 在C#中,我们可以在一个类中定义自己的事件,而其他的类可以注册该事件,当某些事情发生时,可以通知到该类.这对于桌面应用 ...

  7. Lind.DDD.Events领域事件介绍

    回到目录 闲话多说 领域事件大叔感觉是最不好讲的一篇文章,所以拖欠了很久,但最终还是在2015年年前(阴历)把这个知识点讲一下,事件这个东西早在C#1.0时代就有了,那时学起来也是一个费劲,什么是委托 ...

  8. DDD~领域事件与事件总线

    回到目录 谈谈它 终于有些眉目了,搜刮了很多牛人的资料,英文的,中文的,民国文的,终于小有成就了,同时也做了个DEMO,领域事件这东西好,但需要你明白它之后才会说好,而对于明白领域事件这件事来说,它的 ...

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

    回到目录 上一讲主要说了领域事件和领域总线,这并不是一个很容易理解的文章,所以本讲实例篇主要是为了补充上一讲的理论知识,本讲实例关注的是实际中的订单处理模块,我们知道,订单处理是电子商务的核心,往往在 ...

随机推荐

  1. java解惑 读书笔记

    表达式之谜 >奇数性 当取余操作返回一个非0的结果.他与左操作数具有相同的正负符号. >找零谜题 在需要精确答案的地方,要避免使用float和double.对于货币运算.要使用int,lo ...

  2. 2014 Super Training #8 C An Easy Game --DP

    原题:ZOJ 3791 http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3791 题意:给定两个0-1序列s1, s2,操作t ...

  3. java 12-1 StringBuffer类

    线程安全(多线程讲解) 安全 -- 同步 -- 数据是安全的--效率低一些 不安全 -- 不同步 -- 数据不安全--效率高一些 安全和效率问题是永远困扰我们的问题. 安全:医院的网站,银行网站 效率 ...

  4. C#往线程里传递参数

    Thread (ParameterizedThreadStart) 初始化 Thread 类的新实例,指定允许对象在线程启动时传递给线程的委托. Thread (ThreadStart) 初始化 Th ...

  5. 用运算符代替if、else

  6. smarty缓存控制

    第一步初始化配置文件中设置 如果当前访问的模板有缓存就不需要连接数据库那些代码了,如果要模板局部不缓存,要写在iscache外,模板中用{nocache}

  7. raid知识

    1,raid形象理解(饮水机模型) http://dingyichao.blog.51cto.com/442449/698762     2,raid利用率 3,raid详细理解 raid0 raid ...

  8. Integrating JAD decompiler into JDeveloper(转)

    原文地址:Integrating JAD decompiler into JDeveloper In JDeveloper, when debugging or otherwise navigatin ...

  9. C#委托Action、Action<T>、Func<T>、Predicate<T>

    CLR环境中给我们内置了几个常用委托Action. Action<T>.Func<T>.Predicate<T>,一般我们要用到委托的时候,尽量不要自己再定义一 个 ...

  10. Windows下MemCache多端口安装配置

    Windows下MemCache环境安装配置的文章很多,但大部分都是用的默认端口11211,如何修改默认端口.如何在一台服务器上配置多个MemCache端口?这正式本文要解决的问题. 1.从微软官网下 ...