领域事件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~领域事件应用篇(订单处理变得更清晰)
回到目录 上一讲主要说了领域事件和领域总线,这并不是一个很容易理解的文章,所以本讲实例篇主要是为了补充上一讲的理论知识,本讲实例关注的是实际中的订单处理模块,我们知道,订单处理是电子商务的核心,往往在 ...
随机推荐
- 【ASP.NET 基础】表单和控件
1.HTML表单的提交方式 对于一个普通HTML表单来说,它有两个重要的属性:action 和 method.action属性指明当前表单提交之后由哪个程序来处理,这个处理程序可以是任何动态网页或者 ...
- codeforces 709E E. Centroids(树形dp)
题目链接: E. Centroids time limit per test 4 seconds memory limit per test 512 megabytes input standard ...
- HDU 4782 Beautiful Soup --模拟
题意: 将一些分散在各行的HTML代码整理成标签树的形式. 解法: 模拟,具体见代码的讲解. 开始没考虑 '\t' .. 代码: #include <iostream> #include ...
- Android代码规范----按钮单击事件的四种写法
[前言] 按钮少的时候用第三种的匿名内部类会比较快,比如写demo测试的时候或者登陆界面之类. 按钮多的时候一般选择第四种写法. 一.第一种写法:在XML文件中声明onClick属性(很少用) 在XM ...
- 转: Github访问慢解决办法
from: https://yq.aliyun.com/articles/36744 Github访问慢解决办法 zxiaofan 2016-04-20 17:25:00 浏览2156 评论0 摘 ...
- css3爆炸效果更换图片轮播图
思路:给一个div设置一个背景图片1.jpg,然后在这个div上面用两个for循环动态的创建一个列数为C行数为R数量的span,并给这些span设置宽高.定位并设置背景图片0.jpg,然后设置每个sp ...
- C语言 百炼成钢4
//题目10:打印楼梯,同时在楼梯上方打印两个笑脸. #define _CRT_SECURE_NO_WARNINGS #include<stdio.h> #include<stdli ...
- 怎么用JS截取字符串中第一个和第二个字母间的部分?
一.JS中用正则判断字符串是否有匹配正则的字符串部分,格式如下: /[a-zA-Z](.*?)[a-zA-Z]/.test('1a123d45678901a2') “.test”前面的部分是正则表达式 ...
- 地图投影——高斯-克吕格投影、墨卡托投影和UTM投影
地图投影(Map Projection) http://baike.baidu.com/view/94066.htm 概念: 地图投影是把地球表面的任意点,利用一定数学法则,转换到地图平面上的理论和方 ...
- MemCached配置与缓存知识概述
先看看百度百科里面对缓存的介绍: 缓存(Cache memory)是硬盘控制器上的一块内存芯片,具有极快的存取速度,它是硬盘内部存储和外界接口之间的缓冲器.由于硬盘的内部数据传输速度和外界介面传输速度 ...