• DDD事件总线


    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("
    ");
    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

     
    分类: 架构
  • 相关阅读:
    最长公共子序列和最长公共连续子序列 andrew的日志 网易博客
    Best Computer Science Interview Books JiansNet
    分享:Mitmproxy 0.9 发布,支持 SSL 的 HTTP 代理
    创业环境差,被迫“走西口”:一位台湾码农的心路历程
    STLSupport GDB Wiki
    utils C/C++的常用工具类
    题目36 ACM在线评测系统
    DRAMA QUEEN_洪晃在ilook的BLOG
    Codeblocks调试STL——gdb with python support Wanglikai91 博客园
    python urlencode 编码
  • 原文地址:https://www.cnblogs.com/Leo_wl/p/4890453.html
Copyright © 2020-2023  润新知