ASP.NET 设计模式 -- 第14章 订购与支付 (学习笔记)

14.1.1 Order(领域事件框架)

将要创建的领域事件框架基于Udi Dahan(http://www.udidahan.com)设计的框架。

(1)在Agathas.Storefront.Infrastructure项目的Domain文件夹中新建Events文件夹,向其中创建接口IDomainEvent,该接口将标识模型中的领域事件。

namespace Agathas.Storefront.Infrastructure.Domain.Events
{
    public interface IDomainEvent
    {
    }
}

(2)创建IDomainEventHandler接口,这是事件处理程序必须实现的接口。

namespace Agathas.Storefront.Infrastructure.Domain.Events
{
    public interface IDomainEventHandler<T> where T : IDomainEvent
    {
        void Handle(T domainEvent);
    }
}

(3)创建IDomainEventHandlerFactory接口,它是用来获取给定领域事件的领域事件处理程序集合。

namespace Agathas.Storefront.Infrastructure.Domain.Events
{
    public interface IDomainEventHandlerFactory
    {
        IEnumerable<IDomainEventHandler<T>> GetDomainEventHandlersFor<T>(T domainEvent)
                                                                where T : IDomainEvent;
    }
}

(4)添加IDomainEventHandlerFactory接口的一个实现StructureMapDomainEventHandlerFactory,它提供了负责处理给定领域事件的IDomainEventHandler列表。

using System.Collections.Generic;
using StructureMap;

namespace Agathas.Storefront.Infrastructure.Domain.Events
{
    public class StructureMapDomainEventHandlerFactory : IDomainEventHandlerFactory
    {
        public IEnumerable<IDomainEventHandler<T>> GetDomainEventHandlersFor<T>
                                              (T domainEvent) where T : IDomainEvent
        {
            return ObjectFactory.GetAllInstances<IDomainEventHandler<T>>();
        }
    }
}

(5)在获取IDomainEventHandler集合之后,调用它们的处理方法并将领域事件作为动作的实参。添加一个扩展方法IEnumerableExtensions来处理。

using System;
using System.Collections.Generic;

namespace Agathas.Storefront.Infrastructure.Domain.Events
{
    public static class IEnumerableExtensions
    {
        public static void ForEach<T>(this IEnumerable<T> source, Action<T> action)
        {
            foreach (T item in source)
                action(item);
        }
    }
}

(6)为了引发事件,需要创建一个静态类DomainEvents,Model项目中的领域实体将调用该类。

namespace Agathas.Storefront.Infrastructure.Domain.Events
{
    public static class DomainEvents
    {
        public static IDomainEventHandlerFactory DomainEventHandlerFactory { get; set; }

        public static void Raise<T>(T domainEvent) where T : IDomainEvent
        {
            DomainEventHandlerFactory.GetDomainEventHandlersFor(domainEvent)
                                                    .ForEach(h => h.Handle(domainEvent));
        }
    }
}

这样就完成了支持领域事件所需的框架。

因为IOrderState实现引发领域事件,所以现在完成这部分的代码.(代码片段位于Agathas.Storefront.Model\Orders)

(1)创建IOrderState接口

namespace Agathas.Storefront.Model.Orders.States
{
    public interface IOrderState
    {
        int Id { get; set; }
        OrderStatus Status { get; }
        bool CanAddProduct();
        void Submit(Order order);
    }    
}

//需要建立不同的文件
namespace Agathas.Storefront.Model.Orders.States
{
    public enum OrderStatus
    {
        Open = 1,
        Submitted = 2
    }
}
View Code

(2)为了给所有订单状态提供一个基类,创建OrderState抽象类

namespace Agathas.Storefront.Model.Orders.States
{
    public abstract class OrderState : IOrderState
    {
        public virtual int Id { get; set; }

        public abstract OrderStatus Status { get; }

        public abstract bool CanAddProduct();

        public abstract void Submit(Order order);
    }
}
View Code

(3)订单的初始状态为OpenOrderState,当调用Submit方法时,如果订单已经被付款,就引发OrderSubmittedEvent事件。

using Agathas.Storefront.Infrastructure.Domain.Events;
using Agathas.Storefront.Model.Orders.Events;

namespace Agathas.Storefront.Model.Orders.States
{
    public class OpenOrderState : OrderState
    {
        public override OrderStatus Status
        {
            get { return OrderStatus.Open; }
        }

        public override bool CanAddProduct()
        {
            return true;
        }

        public override void Submit(Order order)
        {
            if (order.OrderHasBeenPaidFor())
                order.SetStateTo(OrderStates.Submitted);

            DomainEvents.Raise(new OrderSubmittedEvent() { Order = order });
        }
    }
}

(4)创建上述的OrderSubmittedEvent领域事件

using Agathas.Storefront.Infrastructure.Domain.Events;

namespace Agathas.Storefront.Model.Orders.Events
{
    public class OrderSubmittedEvent : IDomainEvent
    {
        public Order Order { get; set; }
    }
}

(5)创建这个事件的处理程序OrderSubmittedHandler,它将向顾客发送一封电子邮件告知他们订单现在已经提交。

using System;
using System.Text;
using Agathas.Storefront.Infrastructure.Domain.Events;
using Agathas.Storefront.Infrastructure.Email;
using Agathas.Storefront.Model.Orders.Events;

namespace Agathas.Storefront.Services.DomainEventHandlers
{
    public class OrderSubmittedHandler : IDomainEventHandler<OrderSubmittedEvent>
    {
        public void Handle(OrderSubmittedEvent domainEvent)
        {
            StringBuilder emailBody = new StringBuilder();
            string emailAddress = domainEvent.Order.Customer.Email;
            string emailSubject = String.Format("Agatha Order #{0}",
                                                 domainEvent.Order.Id);

            emailBody.AppendLine(String.Format("Hello {0},",
                                 domainEvent.Order.Customer.FirstName));
            emailBody.AppendLine();
            emailBody.AppendLine(
             "The following order will be packed and dispatched as soon as possible.");
            emailBody.AppendLine(domainEvent.Order.ToString());
            emailBody.AppendLine();
            emailBody.AppendLine("Thank you for your custom.");
            emailBody.AppendLine("Agatha's");

            EmailServiceFactory.GetEmailService()
             .SendMail("orders@Agatha.com", emailAddress,
                       emailSubject, emailBody.ToString());
        }
    }
}

 

posted @ 2019-09-19 16:46  FH1004322  阅读(144)  评论(0)    收藏  举报