Back to Directory
The previous lecture focuses on Domain events and bus. This is not an easy-to-understand article. Therefore, this example is mainly used to supplement the theoretical knowledge of the previous lecture, this example focuses on the actual order processing module. We know that order processing is the core of e-commerce, where there are many logics. During development, it brings us a lot of difficulties. How to better separate the focus is the subject of this lecture. This lecture mainly refers to sending notifications to users after the order status is changed, to better illustrate the role of domain events in practice.
Preface a domain event uses the publishing/subscription mode or the observer mode.
Several statuses of an order. When the order enters some statuses, you need to notify the user
Public enum OrderStatus {// <summary> // indicates the created status of the sales order-indicates that the sales order has been created (unused ). /// </Summary> [Description ("user order")] Created = 0, /// <summary> // The order is Canceled by the user /// </summary> [Description ("Cancel order")] Canceled, /// <summary> /// indicates the payment status of the sales order-indicating that the customer has paid the sales order. /// </Summary> [Description ("user Payment")] Paid, /// <summary> /// indicates the delivery status of the sales order. /// </Summary> [Description ("delivered")] Dispatched, /// <summary> /// The order has been completed /// </summary> [Description ("order completed")] Finished ,}
2. Create a domain event data source (originally in a. net event, it is generally an EventArgs object) for the status to be notified)
/// <Summary> /// The Order has confirmed the event source. /// </summary> public class Order_Confirm_Event: Project. events. eventBase {public int OrderId {get; set;} public string UserName {get; set ;}}
/// <Summary> /// order payment event fate /// </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> /// source of the event that the order has been shipped /// </summary> public class Order_Dispatch_Event: Project. events. eventBase {public int OrderId {get; set;} public string UserName {get; set ;}}
3. Add Event handling methods for these event sources
We generally think of it as "behavior". An event source can have multiple types of event behaviors. For example, an order payment event source can have both email and SMS behaviors. Otherwise, an event processing method can also correspond to multiple event sources, such as an email action, which can simultaneously correspond to order payment
And order delivery event sources, so Domain events are very flexible in the project.
/// <Summary> /// Email sending event handling method // call method: EventBus. instance. subscribe <User_Depts_Event> (new SendEmailEventHandler () // EventBus. instance. subscribe <User_Roles_Event> (new SendEmailEventHandler () // </summary> public class Identifier: IEventHandler <Order_Confirm_Event>, IEventHandler <Order_Dispatch_Event>, IEventHandler <Order_Paid_Event> {static string prefix = "this message comes from an email"; # region IE VentHandler <Order_Confirm_Event> member public void Handle (Order_Confirm_Event evt) {Logger. core. loggerFactory. instance. logger_Info (string. format ("Dear customer {0}, your order has been confirmed. Order No. {1}. Please pay as soon as possible! ({2}) [{3}] ", evt. userName, evt. orderId, evt. eventDate, prefix) ;}# endregion # region IEventHandler <Order_Dispatch_Event> member public void Handle (Order_Dispatch_Event evt) {Logger. core. loggerFactory. instance. logger_Info (string. format ("Dear customer {0}, your order has been delivered, order number {1}, please check it! ({2}) [{3}] ", evt. userName, evt. orderId, evt. eventDate, prefix) ;}# endregion # region IEventHandler <Order_Paid_Event> member public void Handle (Order_Paid_Event evt) {Logger. core. loggerFactory. instance. logger_Info (string. format ("Dear customer {0}, your order has been successfully paid, Order No. {1}, payment amount is {2} RMB, we will arrange delivery as soon as possible! ({3}) [{4}] ", evt. UserName, evt. OrderId, evt. TotalPrice, evt. EventDate, prefix);} # endregion}
/// <Summary> /// event handling method of text message // </summary> public class SendSMS_EventHandler: IEventHandler <Order_Confirm_Event>, IEventHandler <Order_Dispatch_Event>, IEventHandler <Order_Paid_Event> {static string prefix = "this message comes from SMS"; # region IEventHandler <Order_Confirm_Event> member public void Handle (Order_Confirm_Event evt) {Logger. core. loggerFactory. instance. logger_Info (string. format ("Dear customer {0}, your order has been confirmed. Order No. {1}, please Pay as soon as possible! ({2}) [{3}] ", evt. userName, evt. orderId, evt. eventDate, prefix) ;}# endregion # region IEventHandler <Order_Dispatch_Event> member public void Handle (Order_Dispatch_Event evt) {Logger. core. loggerFactory. instance. logger_Info (string. format ("Dear customer {0}, your order has been delivered, order number {1}, please check it! ({2}) [{3}] ", evt. userName, evt. orderId, evt. eventDate, prefix) ;}# endregion # region IEventHandler <Order_Paid_Event> member public void Handle (Order_Paid_Event evt) {Logger. core. loggerFactory. instance. logger_Info (string. format ("Dear customer {0}, your order has been successfully paid, Order No. {1}, payment amount is {2} RMB, we will arrange delivery as soon as possible! ({3}) [{4}] ", evt. UserName, evt. OrderId, evt. TotalPrice, evt. EventDate, prefix);} # endregion}
4. Subscribe to domain events
We need to have an entry to subscribe to domain events, such as order confirmation events and order Payment Events. A simple practice is to register in a unified manner in global, and a standard and reasonable approach, I think it should be registered in the static construction method of the order controller, because only when the user operates the order-related module can
Issue orders!
/// <Summary> /// constructor of the class to handle things that cannot be found with a specific instance /// </summary> static OrderController () {# region subscribe to related domain events # region subscribe to the sending email processing method 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 # processing method of region subscription and text message 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}
We can see that each order event source is registered with two event processing methods: email and SMS, which will be executed after the corresponding event is triggered (published, publish.
6. Trigger specific events
A specific event is triggered independently in a specific method. Generally, it is completed at the business logic layer.
/// <Summary> // the user places an order: 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> // order payment: 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> // order delivery: 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 });}
8. Finally, let's take a look at the processing page and result
Generated logs
The generated log content is similar to the user's email or SMS content.
After reading this example, I believe you have a clearer understanding of domain events!
Back to Directory
DDD ~ Domain event application (order processing becomes clearer)