事件总线demo

news/2024/7/2 11:04:25

经过几天的努力拜读大牛高手文章,终于对事件总线有所了解,特此记录下来,以免忘记

1、定义相关的接口:

  A  事件接口

 1 public interface IDomainEvent
 2     {
 3         DateTime OccurredOn();
 4 
 5         /// <summary>
 6         /// 设置为已读
 7         /// </summary>
 8         /// <returns></returns>
 9         void Read();
10 
11         /// <summary>
12         /// 是否已读
13         /// </summary>
14         bool IsRead { get; }
15     }

  B  事件订阅接口

    public interface IDomainEventSubscriber{Type SubscribedToEventType();void Handle(object domainEvent);}

2、定义相关实现

  A  事件实现

 public abstract class DomainEvent :  IDomainEvent{public readonly DateTime OccurredOnTime;public string ID;protected DomainEvent(){this.ID = Guid.NewGuid().ToString();this.OccurredOnTime = DateTime.Now;this.IsRead = false;}public DateTime OccurredOn(){return this.OccurredOnTime;}public void Read(){this.IsRead = true;}public bool IsRead { get; private set; }}

  B  事件订阅实现

    public abstract class DomainEventSubscriber<T> : IDomainEventSubscriber where T : IDomainEvent{/// <summary>订阅的事件类型/// </summary>/// <returns></returns>public Type SubscribedToEventType(){return typeof(T);}public abstract void HandleEvent(T domainEvent);public void Handle(object domainEvent){if (domainEvent is T){this.HandleEvent((T)domainEvent);}else{throw new NotSupportedException(string.Format("当前订阅者支持的事件类型是:{0},当前事件是:{1}", typeof(T).FullName, domainEvent.GetType().FullName));}}}

3、定义事件总线实现

 public class DomainEventBus{public delegate void DistributeExceptionHandle(IDomainEventSubscriber subscriber, IDomainEvent domainEvent, Exception exception);/// <summary>/// Key:DomainEvent的类型,Value订阅该类型事件的订阅者列表/// </summary>private static readonly Dictionary<Type, List<IDomainEventSubscriber>> _subscribers = new Dictionary<Type, List<IDomainEventSubscriber>>();private static readonly object _lockObj = new object();public event DistributeExceptionHandle DistributeExceptionEvent;private static DomainEventBus _instance;public static DomainEventBus Instance(){if (_instance != null)return _instance;var temp = new DomainEventBus();Interlocked.CompareExchange(ref _instance, temp, null);return temp;}public void Publish<T>(T aDomainEvent) where T : IDomainEvent{if (aDomainEvent.IsRead)return;var registeredSubscribers = _subscribers;if (registeredSubscribers != null){var domainEventType = aDomainEvent.GetType();List<IDomainEventSubscriber> subscribers;if (!registeredSubscribers.TryGetValue(domainEventType, out subscribers)){aDomainEvent.Read();  //未找到订阅者,但是消息还是消费掉。return;}foreach (var domainEventSubscriber in subscribers){var subscribedTo = domainEventSubscriber.SubscribedToEventType();if (subscribedTo == domainEventType || subscribedTo is IDomainEvent){Distribute(domainEventSubscriber, aDomainEvent);}}aDomainEvent.Read();}}private void Distribute(IDomainEventSubscriber subscriber, IDomainEvent domainEvent){try{subscriber.Handle(domainEvent);}catch (Exception ex){OnDistributeExceptionEvent(subscriber, domainEvent, ex);}}public void Subscribe(IDomainEventSubscriber aSubscriber){lock (_lockObj){var registeredSubscribers = _subscribers;var domainEventType = aSubscriber.SubscribedToEventType();List<IDomainEventSubscriber> subscribers;if (!registeredSubscribers.TryGetValue(domainEventType, out subscribers)){subscribers = new List<IDomainEventSubscriber>();registeredSubscribers.Add(domainEventType, subscribers);}if (subscribers.Any(ent => ent.SubscribedToEventType().FullName == aSubscriber.SubscribedToEventType().FullName && ent.GetType().FullName == aSubscriber.GetType().FullName))  //相同的订阅只接收一次。return;subscribers.Add(aSubscriber);}}protected virtual void OnDistributeExceptionEvent(IDomainEventSubscriber subscriber, IDomainEvent domainEvent, Exception exception){var handler = DistributeExceptionEvent;if (handler != null)handler(subscriber, domainEvent, exception);}}

4、定义具体的事件

public class OrderCreated : DomainEventCore.DomainEvent{public string OrderId { get; private set; }public string UserId { get; private set; }public string Receiver { get; private set; }public OrderCreated(string orderId, string userId, string receiver){this.OrderId = orderId;this.UserId = userId;this.Receiver = receiver;}}
View Code

5、定义具体事件触发后要执行的方法

 public class OrderCreatedSubscriberPaymentContext : DomainEventSubscriber<OrderCreated>{public override void HandleEvent(OrderCreated domainEvent){//TODO anythingConsole.WriteLine("Order ID:{0},i have payment",domainEvent.OrderId);}}
View Code
 public class OrderCreatedSubscriberSellingPriceContext : DomainEventSubscriber<OrderCreated>{public override void HandleEvent(OrderCreated domainEvent){//TODO anythingConsole.WriteLine("Order ID:{0},i have show price", domainEvent.OrderId);}}
View Code

6、代码测试

class Program{static void Main(string[] args){//事件订阅DomainEventBus.Instance().Subscribe(new OrderCreatedSubscriberSellingPriceContext());DomainEventBus.Instance().Subscribe(new OrderCreatedSubscriberPaymentContext());var tempGuid = Guid.NewGuid().ToString();var entity = new OrderCreated(tempGuid, "mikechang", "sprite");Console.WriteLine("生产一个新的订单:{0}",tempGuid);//事件发布
            DomainEventBus.Instance().Publish(entity);Console.ReadLine();}}

 

转载于:https://www.cnblogs.com/mikechang/p/6390434.html


http://lihuaxi.xjx100.cn/news/242949.html

相关文章

参加java培训,要避免这几个误区!

​ java技术在近几年学习的人越来越多&#xff0c;小编在这里提醒同学们&#xff0c;想要学好java技术&#xff0c;除了报班系统培训之外&#xff0c;还要找到适合自己的学习方法&#xff0c;以下几点误区同学们一定要避免! ​  参加java培训&#xff0c;要避免这几个误区! 1…

leetcode--删除排序数组中的重复项--python

文章目录题目题目详情示例说明解题代码思路代码运行结果最佳方案题目 题目详情 给定一个排序数组&#xff0c;你需要在原地删除重复出现的元素&#xff0c;使得每个元素只出现一次&#xff0c;返回移除后数组的新长度。 不要使用额外的数组空间&#xff0c;你必须在原地修改…

Android中对Log日志文件的分析[转]

一&#xff0c;Bug出现了&#xff0c; 需要“干掉”它 bug一听挺吓人的&#xff0c;但是只要你懂了&#xff0c;android里的bug是很好解决的&#xff0c;因为android里提供了LOG机制&#xff0c;具体的底层代码&#xff0c;以后在来分析&#xff0c;只要你会看bug&#xff0c;a…

转:C#中Monitor对象与Lock关键字的区别分析

Monitor对象1.Monitor.Enter(object)方法是获取 锁&#xff0c;Monitor.Exit(object)方法是释放锁&#xff0c;这就是Monitor最常用的两个方法&#xff0c;当然在使用过程中为了避免获取锁之后因为异常&#xff0c;致锁 无法释放&#xff0c;所以需要在try{} catch(){}之后的fi…

接口测试要如何做数据准备

数据准备是接口测试过程中不可或缺的一步&#xff0c;也是花费时间很长的工作&#xff0c;因为程序的功能就是处理数据。那么在接口测试中&#xff0c;我们要怎样来准备数据呢?小编整理了以下一些关于数据准备的方法&#xff0c;希望对大家能有所帮助。 数据准备分为两种类型&…

舆情,文本挖掘

MLE&#xff0c;MAP&#xff0c;EM 和 point estimation 之间的关系是怎样的 和点估计相对应的是区间估计&#xff0c;这个一般入门的统计教材里都会讲。直观说&#xff0c;点估计一般就是要找概率密度曲线上值最大的那个点&#xff0c;区间估计则要寻找该曲线上满足某种条件的…

leetcode--删除排序链表中的重复元素--python

文章目录题目题目详情示例解题代码思路代码运行结果最佳方案题目 题目详情 给定一个排序链表&#xff0c;删除所有重复的元素&#xff0c;使得每个元素只出现一次。 示例 输入: 1->1->2 输出: 1->2输入: 1->1->2->3->3 输出: 1->2->3解题代码 …

学好web前端开发要注意哪些问题

web前端学起来是比较困难的&#xff0c;当然想要学好web前端技术&#xff0c;那么有一些注意事项一定是要看的&#xff0c;下面小编就为大家详细的介绍一下学好web前端开发要注意哪些问题? ​  学好web前端开发要注意哪些问题? 基础&#xff1a;无论做什么都一定要有扎实的…