回到目錄html
上一講主要說了領域事件和領域總線,這並非一個很容易理解的文章,因此本講實例篇主要是爲了補充上一講的理論知識,本講實例關注的是實際中的訂單處理模塊,咱們知道,訂單處理是電子商務的核心,每每在這裏面,會有不少邏輯,在開發時,給咱們帶來了很多的難度,如何更好的分離關注點,是本講的主題;本講主要是修改訂單狀態後,爲用戶發通知爲例,來以此更好的說一下領域事件在實際中的做用。設計模式
前言 領域事件使用的設計模式是發佈/訂閱模式,或者叫觀察者模式。spa
public enum OrderStatus { /// <summary> /// 表示銷售訂單的已建立狀態 - 代表銷售訂單已被建立(未用)。 /// </summary> [Description("用戶下單")] Created = 0, /// <summary> /// 訂單被用戶取消 /// </summary> [Description("取消訂單")] Canceled, /// <summary> /// 表示銷售訂單的已付款狀態 - 代表客戶已向銷售訂單付款。 /// </summary> [Description("用戶付款")] Paid, /// <summary> /// 表示銷售訂單的已發貨狀態。 /// </summary> [Description("已經發貨")] Dispatched, /// <summary> /// 訂單已經完成 /// </summary> [Description("訂單完成")] Finished, }
/// <summary> /// 訂單已經確認事件源 /// </summary> public class Order_Confirm_Event : Project.Events.EventBase { public int OrderId { get; set; } public string UserName { get; set; } }
/// <summary> /// 訂單已經付款事件緣 /// </summary> public class Order_Paid_Event : Project.Events.EventBase { public int OrderId { get; set; } public string UserName { get; set; } public decimal TotalPrice { get; set; } }
/// <summary> /// 訂單已經發貨事件源 /// </summary> public class Order_Dispatch_Event : Project.Events.EventBase { public int OrderId { get; set; } public string UserName { get; set; } }
咱們通常理解爲「行爲」,一種事件源能夠有多種事件行爲,如一個訂單付款事件源,它能夠同時有電子郵件行爲和短信行爲;反之,一個事件處理方式也能夠對應多個事件源,如一個電子郵件行爲,它能夠同時對應訂單付款.net
和訂單發貨等事件源,因此,領域事件在項目中是很是靈活的。設計
/// <summary> /// 發Email的事件處理方式 /// 調用方法:EventBus.Instance.Subscribe<User_Depts_Event>(new SendEmailEventHandler()) /// EventBus.Instance.Subscribe<User_Roles_Event>(new SendEmailEventHandler()) /// </summary> public class SendEmail_EventHandler : IEventHandler<Order_Confirm_Event>, IEventHandler<Order_Dispatch_Event>, IEventHandler<Order_Paid_Event> { static string prefix = "本消息來自電子郵件"; #region IEventHandler<Order_Confirm_Event> 成員 public void Handle(Order_Confirm_Event evt) { Logger.Core.LoggerFactory.Instance.Logger_Info(string.Format("尊敬的客戶{0},你的訂單已經確認,訂單號{1},請儘快付款!({2})[{3}]" , evt.UserName , evt.OrderId , evt.EventDate , prefix)); } #endregion #region IEventHandler<Order_Dispatch_Event> 成員 public void Handle(Order_Dispatch_Event evt) { Logger.Core.LoggerFactory.Instance.Logger_Info(string.Format("尊敬的客戶{0},你的訂單已經發貨,訂單號{1},請注意查收!({2})[{3}]" , evt.UserName , evt.OrderId , evt.EventDate , prefix)); } #endregion #region IEventHandler<Order_Paid_Event> 成員 public void Handle(Order_Paid_Event evt) { Logger.Core.LoggerFactory.Instance.Logger_Info(string.Format("尊敬的客戶{0},你的訂單已經成功付款,訂單號{1},付款金額爲{2}元,咱們會盡快安排發貨!({3})[{4}]" , evt.UserName , evt.OrderId , evt.TotalPrice , evt.EventDate , prefix)); } #endregion }
/// <summary> /// 發短信的事件處理方式 /// </summary> public class SendSMS_EventHandler : IEventHandler<Order_Confirm_Event>, IEventHandler<Order_Dispatch_Event>, IEventHandler<Order_Paid_Event> { static string prefix = "本消息來自短信"; #region IEventHandler<Order_Confirm_Event> 成員 public void Handle(Order_Confirm_Event evt) { Logger.Core.LoggerFactory.Instance.Logger_Info(string.Format("尊敬的客戶{0},你的訂單已經確認,訂單號{1},請儘快付款!({2})[{3}]" , evt.UserName , evt.OrderId , evt.EventDate , prefix)); } #endregion #region IEventHandler<Order_Dispatch_Event> 成員 public void Handle(Order_Dispatch_Event evt) { Logger.Core.LoggerFactory.Instance.Logger_Info(string.Format("尊敬的客戶{0},你的訂單已經發貨,訂單號{1},請注意查收!({2})[{3}]" , evt.UserName , evt.OrderId , evt.EventDate , prefix)); } #endregion #region IEventHandler<Order_Paid_Event> 成員 public void Handle(Order_Paid_Event evt) { Logger.Core.LoggerFactory.Instance.Logger_Info(string.Format("尊敬的客戶{0},你的訂單已經成功付款,訂單號{1},付款金額爲{2}元,咱們會盡快安排發貨!({3})[{4}]" , evt.UserName , evt.OrderId , evt.TotalPrice , evt.EventDate , prefix)); } #endregion }
咱們須要有一個入口來訂閱領域事件,如訂閱訂單確認事件,訂單付款事件等,簡單的作法是在global裏統一註冊,而標準合理的做法,我以爲應該在訂單controller的靜態構造方法裏去註冊它,由於只有用戶操做訂單相關模塊時,纔可能觸日誌
發訂單這些事件!code
/// <summary> /// 類的構造方法,處理與具體實例沒法的東西 /// </summary> static OrderController() { #region 訂閱相關領域事件 #region 訂閱發email處理方式 EventBus.Instance.Subscribe<Order_Confirm_Event>(new SendEmail_EventHandler()); EventBus.Instance.Subscribe<Order_Dispatch_Event>(new SendEmail_EventHandler()); EventBus.Instance.Subscribe<Order_Paid_Event>(new SendEmail_EventHandler()); #endregion #region 訂閱發短信的處理方式 EventBus.Instance.Subscribe<Order_Confirm_Event>(new SendSMS_EventHandler()); EventBus.Instance.Subscribe<Order_Dispatch_Event>(new SendSMS_EventHandler()); EventBus.Instance.Subscribe<Order_Paid_Event>(new SendSMS_EventHandler()); #endregion #endregion }
咱們看到了,每種訂單事件源都被註冊了電子郵件和短信兩種事件處理方式,這在對應的事件被觸發(發佈,publish)以後,它們會被執行。orm
具體的事件在具體的方法裏,獨立的去觸發,通常它會在業務邏輯層完成htm
/// <summary> /// 用戶下單:create /// </summary> /// <param name="entity"></param> public void DoOrder(Order_Info entity) { entity.OrderStatus = (int)OrderStatus.Created; _orderRepository.Insert(entity); entity.Order_Detail.ToList().ForEach(j => j.OrderId = entity.Id); _orderDetailRepository.Insert(entity.Order_Detail); EventBus.Instance.Publish(new Order_Confirm_Event { OrderId = entity.Id, UserName = entity.UserName }); } /// <summary> /// 訂單付款:paid /// </summary> /// <param name="entity"></param> public void PaidOrder(Order_Info entity) { entity.OrderStatus = (int)OrderStatus.Paid; _orderRepository.Update(entity); EventBus.Instance.Publish(new Order_Paid_Event { OrderId = entity.Id, TotalPrice = entity.TotalPrice, UserName = entity.UserName }); } /// <summary> /// 訂單發貨:dispatch /// </summary> /// <param name="entity"></param> public void DispatchOrder(Order_Info entity) { entity.OrderStatus = (int)OrderStatus.Dispatched; _orderRepository.Update(entity); EventBus.Instance.Publish(new Order_Dispatch_Event { OrderId = entity.Id, UserName = entity.UserName }); }
八 最後,咱們看一下處理處理頁面和結果的截圖對象
生成的日誌
生成的日誌內容,相似於用戶上到的電子郵件或者短信的內容
怎麼樣,看完這個例子相信您對領域事件有了更清晰的認識了吧,呵呵!