领域事件DomainEvents

时间:2023-03-09 09:05:48
领域事件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("送餐超时了...");
        }
    }