您的位置:首页 > 其它

DDD事件总线

2015-10-18 22:06 681 查看

DDD事件总线

基本思路:

(1) 在事件总线内部维护着一个事件与事件处理程序相映射的字典。

(2) 利用反射,事件总线会将实现了IEventHandler的处理程序与相应事件关联到一起,相当于实现了事件处理程序对事件的订阅。

(3) 当发布事件时,事件总线会从字典中找出相应的事件处理程序,然后利用反射去调用事件处理程序中的方法。

核心类(事件总线类)

1 using System;
2 using System.Collections.Generic;
3 using System.Linq;
4 using System.Reflection;
5
6
7 namespace Framework.EventBus
8 {
9     public class EventBus
10     {
11
12         private static EventBus _eventBus = null;
13
14         private static Dictionary<Type, List<Type>> _eventMapping = new Dictionary<Type, List<Type>>();  // 在这个字典中,key存储的是事件,而value中存储的是事件处理程序
15
16
17         private EventBus() { }
18         /// <summary>
19         /// 单例
20         /// </summary>
21         /// <returns></returns>
22         public static EventBus Instance()
23         {
24             if (_eventBus == null)
25             {
26                 _eventBus = new EventBus();
27                 MapEvent2Handler();
28             }
29             return _eventBus;
30         }
31
32
33
34         /// <summary>
35         /// 发布
36         /// 这里没有用到队列之类的东西,使用的是直接调用的方式
37         /// </summary>
38         /// <param name="eventData"></param>
39         public void Publish(BaseEvent eventData)
40         {
41             // 找出这个事件对应的处理者
42             Type eventType = eventData.GetType();
43
44             if (_eventMapping.ContainsKey(eventType) == true)
45             {
46                 foreach (Type item in _eventMapping[eventType])
47                 {
48                     MethodInfo mi = item.GetMethod("Handle");
49                     if (mi != null)
50                     {
51                         object o = Activator.CreateInstance(item);
52                         mi.Invoke(o, new object[] { eventData });
53                     }
54                 }
55
56             }
57         }
58
59
60
61
62
63         /// <summary>
64         /// 将事件与事件处理程序映射到一起
65         /// 使用元数据来进行注册
66         /// </summary>
67         static void MapEvent2Handler()
68         {
69             Assembly assembly = Assembly.GetExecutingAssembly();
70             Type[] types = assembly.GetTypes();
71
72             foreach (Type type in types)
73             {
74                 Type handlerInterfaceType = type.GetInterface("IEventHandler`1");  // 事件处理者
75
76                 if (handlerInterfaceType != null) // 若是事件处理者,则以其泛型参数为key,事件处理者的集合为value添加到映射中
77                 {
78                     Type eventType = handlerInterfaceType.GetGenericArguments()[0]; // 这里只有一个
79                     // 查找是否存在key
80                     if (_eventMapping.Keys.Contains(eventType))
81                     {
82                         List<Type> handlerTypes = _eventMapping[eventType];
83                         handlerTypes.Add(type);
84                         _eventMapping[eventType] = handlerTypes;
85                     }
86                     else // 存在则添加
87                     {
88                         List<Type> handlerTypes = new List<Type>();
89                         handlerTypes.Add(type);
90                         _eventMapping.Add(eventType, handlerTypes);
91                     }
92                 }
93             }
94         }
95
96     }
97 }


核心类(事件基类)

1 using System;
2 using System.Collections.Generic;
3 using System.Linq;
4 using System.Text;
5
6 namespace Framework.EventBus
7 {
8     public class BaseEvent
9     {
10
11         /// <summary>
12         /// 事件发生的时间
13         /// </summary>
14         public DateTime EventTime { get; set; }
15
16         /// <summary>
17         /// 事件源
18         /// </summary>
19         public object EventSource { get; set; }
20
21
22     }
23 }


核心类(事件处理程序接口)

1 namespace Framework.EventBus
2 {
3     public interface IEventHandler<T>
4         where T : BaseEvent
5     {
6         void Handle(T eventData);
7     }
8 }


使用方法

实现接口IEventHandler<T>

1 using System;
2 using System;
3 using System.Collections.Generic;
4 using System.Linq;
5 using System.Text;
6
7
8 namespace Framework.EventBus
9 {
10     /// <summary>
11     /// 实现了IEventHandler<OrderAddedEvent>接口,就是订阅了OrderAddedEvent事件
12     /// </summary>
13     public class OrderAddedEventHandler1 : IEventHandler<OrderAddedEvent>
14     {
15         public void Handle(OrderAddedEvent eventData)
16         {
17
18             Console.WriteLine("\r\n");
19             Console.WriteLine("订单的数据是:" );
20             Console.WriteLine("  订单号:" + eventData.Order.OrderId);
21             Console.WriteLine("  订单金额:" + eventData.Order.OrderAmount);
22             Console.WriteLine("  下单时间:" + eventData.Order.OrderDateTime);
23
24         }
25     }
26 }


注:实现了IEventHandler<OrderAddedEvent>接口,就是订阅了OrderAddedEvent事件

订单类

1 public class OrderEntity
2 {
3
4     /// <summary>
5     /// 订单编号
6     /// </summary>
7     public string OrderId { get; set; }
8
9
10     /// <summary>
11     /// 下单日期
12     /// </summary>
13     public DateTime OrderDateTime { get; set; }
14
15
16     /// <summary>
17     /// 订单金额
18     /// </summary>
19     public decimal OrderAmount { get; set; }
20
21 }


发布事件

1 using System;
2 using System.Collections.Generic;
3 using System.Linq;
4 using System.Text;
5
6
7 namespace Framework.EventBus
8 {
9     class Program
10     {
11         static void Main(string[] args)
12         {
13             EventBus bus = EventBus.Instance();
14
15             OrderEntity order = new OrderEntity() { OrderId = "20151017001", OrderDateTime = DateTime.Now, OrderAmount = 500 };
16             bus.Publish(new OrderAddedEvent() { EventTime = DateTime.Now, Order = order }); // 发布OrderAddedEvent事件,
17
19             Console.Read();
20         }
21
22     }
23 }


运行结果



改进

(1)实现基于msmq的事件总线,使得系统能够进行分布式的事件订阅和发布。

下载

示例代码

参考资料

aspnetboilerplate
https://github.com/aspnetboilerplate/aspnetboilerplate
分享一个分布式消息总线,基于.NET Socket Tcp的发布-订阅框架
http://www.cxyclub.cn/n/53667/
Guava - EventBus(事件总线)
http://greengerong.com/blog/2014/11/27/guava-eventbus/
DDD~领域事件与事件总线
http://www.cnblogs.com/lori/p/3476703.html
事件总线 EventBus的设计
http://www.cnblogs.com/MartinChen999/archive/2011/12/21/2294034.html
分类: 架构
标签: 事件总线, Event Bus
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: