静态类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. 【ASP.NET 基础】表单和控件

    1.HTML表单的提交方式 对于一个普通HTML表单来说,它有两个重要的属性:action 和 method.action属性指明当前表单提交之后由哪个程序来处理,这个处理程序可以是任何动态网页或者 ...

  2. codeforces 709E E. Centroids(树形dp)

    题目链接: E. Centroids time limit per test 4 seconds memory limit per test 512 megabytes input standard ...

  3. HDU 4782 Beautiful Soup --模拟

    题意: 将一些分散在各行的HTML代码整理成标签树的形式. 解法: 模拟,具体见代码的讲解. 开始没考虑 '\t' .. 代码: #include <iostream> #include ...

  4. Android代码规范----按钮单击事件的四种写法

    [前言] 按钮少的时候用第三种的匿名内部类会比较快,比如写demo测试的时候或者登陆界面之类. 按钮多的时候一般选择第四种写法. 一.第一种写法:在XML文件中声明onClick属性(很少用) 在XM ...

  5. 转: Github访问慢解决办法

    from: https://yq.aliyun.com/articles/36744 Github访问慢解决办法   zxiaofan 2016-04-20 17:25:00 浏览2156 评论0 摘 ...

  6. css3爆炸效果更换图片轮播图

    思路:给一个div设置一个背景图片1.jpg,然后在这个div上面用两个for循环动态的创建一个列数为C行数为R数量的span,并给这些span设置宽高.定位并设置背景图片0.jpg,然后设置每个sp ...

  7. C语言 百炼成钢4

    //题目10:打印楼梯,同时在楼梯上方打印两个笑脸. #define _CRT_SECURE_NO_WARNINGS #include<stdio.h> #include<stdli ...

  8. 怎么用JS截取字符串中第一个和第二个字母间的部分?

    一.JS中用正则判断字符串是否有匹配正则的字符串部分,格式如下: /[a-zA-Z](.*?)[a-zA-Z]/.test('1a123d45678901a2') “.test”前面的部分是正则表达式 ...

  9. 地图投影——高斯-克吕格投影、墨卡托投影和UTM投影

    地图投影(Map Projection) http://baike.baidu.com/view/94066.htm 概念: 地图投影是把地球表面的任意点,利用一定数学法则,转换到地图平面上的理论和方 ...

  10. MemCached配置与缓存知识概述

    先看看百度百科里面对缓存的介绍: 缓存(Cache memory)是硬盘控制器上的一块内存芯片,具有极快的存取速度,它是硬盘内部存储和外界接口之间的缓冲器.由于硬盘的内部数据传输速度和外界介面传输速度 ...