找回密码
 立即注册
首页 业界区 业界 事件总线的设计与实现

事件总线的设计与实现

啖曼烟 2025-6-9 09:39:16
事件总线(在有些框架中也称时间聚合器,如Prism的EventAggregater)是订阅-发布模式的一种实现,类似观察者模式,相对于观察者模式,事件总线更灵活,它是一种集中处理事件的模式,允许不同组件之间通信,降低耦合度。
事件总线的三要素:事件源(事件的定义)、发布事件(触发事件)、订阅事件(事件的应答实现)。
实现事件总线,主要工作是事件基类、参数基类、事件自动注册的定义,基于需求场景的业务型事件,只需要按照预定义的规则增加上述三要素即可,大大降低业务复杂度,且可实现一对一、一对多,多对一,同步应答、异步应答等方式。
1、定义事件基类(抽象类)
  1.     public abstract class MyEventBase
  2.     {
  3.         public string EventName { get; set; }
  4.     }
复制代码
2、事件参数的基类(抽象类)
  1.     public abstract class MyEventArgs<T>:EventArgs
  2.     {
  3.         public T Argument { get; set; }
  4.     }
复制代码
3、事件的基类(无返回值的事件基类,因无返回值,可异步调用,也可同步调用,建议异步调用)
  1.    public class MyEvent<T>: MyEventBase where T : EventArgs
  2.    {
  3.        protected static readonly object lockObject = new object();
  4.        protected readonly List> subscribers = new List>();
  5.        public void Subscribe(Action<object, T> eventHandler)
  6.        {
  7.            lock (lockObject)
  8.            {
  9.                if (!subscribers.Contains(eventHandler))
  10.                {
  11.                    subscribers.Add(eventHandler);
  12.                }
  13.            }
  14.        }
  15.        public void Unsubscribe(Action<object, T> eventHandler)
  16.        {
  17.            lock (lockObject)
  18.            {
  19.                if (subscribers.Contains(eventHandler))
  20.                {
  21.                    subscribers.Remove(eventHandler);
  22.                }
  23.            }
  24.        }
  25.        public virtual void Publish(object sender, T eventArgs)
  26.        {
  27.            lock (lockObject)
  28.            {
  29.                for (int i = 0; i < subscribers.Count; i++)
  30.                {
  31.                    subscribers[i](sender, eventArgs);
  32.                }
  33.            }
  34.        }
  35.    }
复制代码
4、事件的基类(有返回值事件的基类,因需要获取返回值,一般采用同步方式调用)
  1.     public class MyEventWithResult<T1, T2> : MyEventBase where T1 : EventArgs
  2.     {
  3.         protected static readonly object lockObject = new object();
  4.         protected readonly List<Func<object, T1, T2>> subscribers = new List<Func<object, T1, T2>>();
  5.         public void Subscribe(Func<object, T1, T2> eventHandler)
  6.         {
  7.             lock (lockObject)
  8.             {
  9.                 if (!subscribers.Contains(eventHandler))
  10.                 {
  11.                     subscribers.Add(eventHandler);
  12.                 }
  13.             }
  14.         }
  15.         public void Unsubscribe(Func<object, T1, T2> eventHandler)
  16.         {
  17.             lock (lockObject)
  18.             {
  19.                 if (subscribers.Contains(eventHandler))
  20.                 {
  21.                     subscribers.Remove(eventHandler);
  22.                 }
  23.             }
  24.         }
  25.         public virtual T2 Publish(object sender, T1 eventArgs)
  26.         {
  27.             T2 result = default;
  28.             lock (lockObject)
  29.             {
  30.                 for (int i = 0; i < subscribers.Count; i++)
  31.                 {
  32.                     result = subscribers[i](sender, eventArgs);
  33.                 }
  34.             }
  35.             return result;
  36.         }
  37.     }
复制代码
5、事件中心,负责自动装载事件
  1.     public class MyEventAggregator
  2.     {
  3.         private static MyEventAggregator _default;
  4.         private static readonly object _locker = new object();
  5.         private readonly Dictionary<Type, MyEventBase> _eventAggregator = new Dictionary<Type, MyEventBase>();
  6.         /// <summary>
  7.         /// 默认事件总线实例,建议只使用此实例
  8.         /// </summary>
  9.         public static MyEventAggregator Default
  10.         {
  11.             get
  12.             {
  13.                 if (_default == null)
  14.                 {
  15.                     lock (_locker)
  16.                     {
  17.                         // 如果类的实例不存在则创建,否则直接返回
  18.                         if (_default == null)
  19.                         {
  20.                             _default = new MyEventAggregator();
  21.                         }
  22.                     }
  23.                 }
  24.                 return _default;
  25.             }
  26.         }
  27.         /// <summary>
  28.         /// 构造函数,自动加载EventBase的派生类实现
  29.         /// </summary>
  30.         public MyEventAggregator()
  31.         {
  32.             Type type = typeof(MyEventBase);
  33.             Assembly assembly = Assembly.GetAssembly(type);
  34.             //注册时需排除的基类
  35.             Type typeMyEvent = typeof(MyEvent<>);
  36.             Type typeMyEventWithResult = typeof(MyEventWithResult<,>);
  37.             List<Type> typeList2 = assembly.GetTypes()
  38.                 .Where(t => t != type && t!=typeAnalysisEvent && t != typeMyEventWithResult && type.IsAssignableFrom(t))
  39.                 .ToList();
  40.             foreach (var item in typeList2)
  41.             {
  42.                 MyEventBase eventBase = (MyEventBase)assembly.CreateInstance(item.FullName);
  43.                 _eventAggregator.Add(item, eventBase);
  44.             }
  45.         }
  46.         /// <summary>
  47.         /// 获取事件实例
  48.         /// </summary>
  49.         /// <typeparam name="TEvent">事件类型</typeparam>
  50.         /// <returns></returns>
  51.         public TEvent GetEvent<TEvent>() where TEvent : MyEventBase
  52.         {
  53.             return (TEvent)_eventAggregator[typeof(TEvent)];
  54.         }
  55.         /// <summary>
  56.         /// 添加事件类型
  57.         /// </summary>
  58.         /// <typeparam name="TEvent"></typeparam>
  59.         public void AddEvent<TEvent>() where TEvent : MyEventBase, new()
  60.         {
  61.             lock (_locker)
  62.             {
  63.                 Type type = typeof(TEvent);
  64.                 if (!_eventAggregator.ContainsKey(type))
  65.                 {
  66.                     _eventAggregator.Add(type, new TEvent());
  67.                 }
  68.             }
  69.         }
  70.         /// <summary>
  71.         /// 移除事件类型
  72.         /// </summary>
  73.         /// <typeparam name="TEvent"></typeparam>
  74.         public void RemoveEvent<TEvent>() where TEvent : MyEventBase, new()
  75.         {
  76.             lock (_locker)
  77.             {
  78.                 Type type = typeof(TEvent);
  79.                 if (_eventAggregator.ContainsKey(type))
  80.                 {
  81.                     _eventAggregator.Remove(type);
  82.                 }
  83.             }
  84.         }
  85.     }
  86. }
复制代码
6、具体事件的定义和调用示例
定义
  1.     /// <summary>
  2.     /// 添加日志 事件
  3.     /// </summary>
  4.     public class WriteLogEvent : MyEvent<WriteLogEventArgs>
  5.     {
  6.         public override void Publish(object sender, WriteLogEventArgs eventArgs)
  7.         {
  8.             for (int i = 0; i < subscribers.Count; i++)
  9.             {
  10.                 var action = subscribers[i];
  11.                 Task.Run(() => action(sender, eventArgs));
  12.             }
  13.         }
  14.     }
  15.     public class WriteLogEventArgs : MyEventArgs<WriteLogEventArgs2> { };
  16.     public class WriteLogEventArgs2
  17.     {
  18.         /// <summary>
  19.         /// 日志内容
  20.         /// </summary>
  21.         public string Msg { get; set; }
  22.         /// <summary>
  23.         /// 操作类型
  24.         /// </summary>
  25.         public OperationType OperationType { get; set; }
  26.         /// <summary>
  27.         /// 备注
  28.         /// </summary>
  29.         public string Remark { get; set; }
  30.         /// <summary>
  31.         /// 目标类型
  32.         /// </summary>
  33.         public LogTargetType LogTargetType { get; set; }
  34.         /// <summary>
  35.         /// 目标值
  36.         /// </summary>
  37.         public string TargetValue { get; set; }
  38.     }
复制代码
发布事件
  1. MyEventAggregator.Default.GetEvent<WriteLogEvent>().Publish(this, new WriteLogEventArgs
  2. {
  3.     Argument = new WriteLogEventArgs2
  4.     {
  5.         Msg = logMsg,
  6.         OperationType = OperationType.Save,
  7.         LogTargetType = LogTargetType.OriginalData,
  8.         TargetValue = targetValue,
  9.         Remark = _MPIComment
  10.     }
  11. });
复制代码
订阅事件
  1. MyEventAggregator.Default.GetEvent<WriteLogEvent>().Subscribe(WriteLogEventHandler);
  2. private void WriteLogEventHandler(object sender, WriteLogEventArgs e)
  3. {
  4.     -----business logic
  5.     -----
  6. }
复制代码
来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
您需要登录后才可以回帖 登录 | 立即注册