静态类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. uva 10305 ordering tasks(超级烂题)——yhx

    aaarticlea/png;base64,iVBORw0KGgoAAAANSUhEUgAABHIAAAHDCAYAAABI5T2bAAAgAElEQVR4nOydPY7svLW1awQGNABHCm

  2. POJ 1515 Street Directions --一道连通题的双连通和强连通两种解法

    题意:将一个无向图中的双向边改成单向边使图强连通,问最多能改多少条边,输出改造后的图. 分析: 1.双连通做法: 双连通图转强连通图的算法:对双连通图进行dfs,在搜索的过程中就能按照搜索的方向给所有 ...

  3. 怪物彈珠Monster Strike 攻略

    火>水>木>光>暗 1.每天的曜日素材本,周一暗光,周二火,周参水,周四木,周五光乌龟,都是可以打整天的 2.另外补充,升经验用暗乌龟,切忌切记要塞给他随便一只烂宠升等,再吃掉 ...

  4. 通过TTL值判断系统

    我们做网络的渗透测试,开始的时候会ping一下网站判断一下网站使用的系统,默认情况下, UNIX 255 LINUX 64WIN2K/NT 128WINDOWS 32 但是 每经过一个路由器就会减1这 ...

  5. jsp 微信公众平台 token验证(php、jsp)(转载)

    微信公众平台现在推出自动回复消息接口,但是由于是接口内容用的是PHP语言写的,很多地方操作起来让本人这个对java比较熟悉的小伙很别扭,所以仿照PHP的接口代码做了一套jsp语言编写的接口. 首先先把 ...

  6. 梳理git分支管理策略

    如果你严肃对待编程,就必定会使用"版本管理系统"(Version Control System). 眼下最流行的"版本管理系统",非Git莫属. 相比同类软件, ...

  7. SQL查询(医疗项目的SQL复习)

    内容来自于

  8. python socket发送魔法包网络唤醒开机.py

    python socket发送魔法包网络唤醒开机.py 现在的电脑应该都普遍支持有线网络的WOL了,支持无线网络唤醒的电脑,可能比较少. """ python socke ...

  9. 浅谈WebService返回数据效率对比

    原文链接 http://www.dotnetgeek.cn/xuexiwebservice1.html 一.什么是WebService: 简单通俗来说,就是企业之间.网站之间通过Internet来访问 ...

  10. U3D 扩展方法 & Dotween & tolua

    using UnityEngine; using System.Collections; using LuaInterface;//tolua 空间引用 using DG.Tweening;//DOT ...