领域事件DomainEvents
静态类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的更多相关文章
- ABP框架 - 领域事件(EventBus)
文档目录 本节内容: EventBus 注入 IEventBus 获取默认实例 定义事件 预定义事件 处理完异常 实体修改 触发事件 处理事件 处理基类事件 处理程序异常 处理多个事件 处理程序注册 ...
- 如何一步一步用DDD设计一个电商网站(十三)—— 领域事件扩展
阅读目录 前言 回顾 本地的一致性 领域事件发布出现异常 订阅者处理出现异常 结语 一.前言 上篇中我们初步运用了领域事件,其中还有一些问题我们没有解决,所以实现是不健壮的,下面先来回顾一下. 二.回 ...
- DDD领域驱动设计:领域事件
1 前置阅读 在阅读本文章之前,你可以先阅读: DDD领域驱动设计是什么 DDD领域驱动设计:实体.值对象.聚合根 DDD领域驱动设计:仓储 MediatR一个优秀的.NET中介者框架 2 什么是领域 ...
- 重新整理 .net core 实践篇—————领域事件[二十九]
前文 前面整理了仓储层,工作单元模式,同时简单介绍了一下mediator. 那么就mediator在看下领域事件启到了什么作用吧. 正文 这里先注册一下MediatR服务: // 注册中间者:Medi ...
- ABP(现代ASP.NET样板开发框架)系列之14、ABP领域层——领域事件(Domain events)
点这里进入ABP系列文章总目录 基于DDD的现代ASP.NET开发框架--ABP系列之14.ABP领域层——领域事件(Domain events) ABP是“ASP.NET Boilerplate P ...
- ABP理论学习之事件总线和领域事件
返回总目录 本篇目录 事件总线 定义事件 触发事件 处理事件 句柄注册 取消注册 在C#中,我们可以在一个类中定义自己的事件,而其他的类可以注册该事件,当某些事情发生时,可以通知到该类.这对于桌面应用 ...
- Lind.DDD.Events领域事件介绍
回到目录 闲话多说 领域事件大叔感觉是最不好讲的一篇文章,所以拖欠了很久,但最终还是在2015年年前(阴历)把这个知识点讲一下,事件这个东西早在C#1.0时代就有了,那时学起来也是一个费劲,什么是委托 ...
- DDD~领域事件与事件总线
回到目录 谈谈它 终于有些眉目了,搜刮了很多牛人的资料,英文的,中文的,民国文的,终于小有成就了,同时也做了个DEMO,领域事件这东西好,但需要你明白它之后才会说好,而对于明白领域事件这件事来说,它的 ...
- DDD~领域事件应用篇(订单处理变得更清晰)
回到目录 上一讲主要说了领域事件和领域总线,这并不是一个很容易理解的文章,所以本讲实例篇主要是为了补充上一讲的理论知识,本讲实例关注的是实际中的订单处理模块,我们知道,订单处理是电子商务的核心,往往在 ...
随机推荐
- 如何在ZBrush中添加毛发
ZBrush不仅能雕刻出完美的头发造型,还能够应用真实的头发和毛发.在制作毛发之前只需要简单定义遮罩区域,包括长短.疏密.当然,最重要的是,你可以使用Polypaint生成各种有色纤维,这将非常方便. ...
- CSS3属性选择器与(:not)选择器
一:css3属性选择器: img[alt]{ border:2px dashed #000; } 这个选择器会匹配页面标签中任何一个含有alt属性的图片标签. 还可以通过设定属性值来缩小匹配范围: ...
- POJ 3264 Balanced Lineup -- RMQ或线段树
一段区间的最值问题,用线段树或RMQ皆可.两种代码都贴上:又是空间换时间.. RMQ 解法:(8168KB 1625ms) #include <iostream> #include < ...
- bootstrap学习总结-css样式设计(一)
由于项目需要,所以打算好好学习下bootstrap框架,之前了解一点,框架总体不难,但涉及到的东西还是很多,想要熟练掌握它,还是要多练练. 一:bootstrap是什么? bs是什么? 即前端页面搭 ...
- C++学习之开发环境搭建篇(一)
由于C++是一门非跨平台语言,其开发的程序编译生成的可执行文件,只能在相应的操作系统中被执行,离开此系统环境将无法执行. 主要原因是不同的操作系统,可执行文件的结构不同,最为常见的操作系统是有:MAC ...
- java 8-8 接口的练习
/* 老师和学生案例,加入抽烟的额外功能 分析: 老师和学生都具有共同的变量:名字,年龄 共同的方法:吃饭,睡觉 老师有额外的功能:抽烟(设定个接口),部分抽烟 有共同的变量和方法,设一个父类:per ...
- ArcGis 中MapControl 框选
void mCtrl_OnMouseDown(object sender, ESRI.ArcGIS.Controls.IMapControlEvents2_OnMouseDownEvent e) ...
- relative 和 absolute
relative总是相对于其最近的父层 absolute总是相对于其最近的定义为relative或absolute的父层
- 使用SilverLight开发区域地图分析模块
本人最近接收开发一个代码模块,功能主要是在页面上显示安徽省市地图,并且在鼠标移动到地图某市区域时,显示当前区域的各类信息等,一开始准备用百度地图,高德地图等地图工具进行开发,最后发现都不适合进行此类开 ...
- [Unity3D] 和Unity3D的一些事
Before 一开始知道Unty3D引擎,貌似还是大一或者大二,那时Unity3D还是收费软件,不像现在Personal Version免费. XNA|MonoGame 再后来,在Coursera上发 ...