事件总线的设计与实现
事件总线(在有些框架中也称时间聚合器,如Prism的EventAggregater)是订阅-发布模式的一种实现,类似观察者模式,相对于观察者模式,事件总线更灵活,它是一种集中处理事件的模式,允许不同组件之间通信,降低耦合度。
事件总线的三要素:事件源(事件的定义)、发布事件(触发事件)、订阅事件(事件的应答实现)。
实现事件总线,主要工作是事件基类、参数基类、事件自动注册的定义,基于需求场景的业务型事件,只需要按照预定义的规则增加上述三要素即可,大大降低业务复杂度,且可实现一对一、一对多,多对一,同步应答、异步应答等方式。
1、定义事件基类(抽象类)
public abstract class MyEventBase
{
public string EventName { get; set; }
}
2、事件参数的基类(抽象类)
public abstract class MyEventArgs<T>:EventArgs
{
public T Argument { get; set; }
}
3、事件的基类(无返回值的事件基类,因无返回值,可异步调用,也可同步调用,建议异步调用)
public class MyEvent<T>: MyEventBase where T : EventArgs
{
protected static readonly object lockObject = new object();
protected readonly List<Action<object, T>> subscribers = new List<Action<object, T>>();
public void Subscribe(Action<object, T> eventHandler)
{
lock (lockObject)
{
if (!subscribers.Contains(eventHandler))
{
subscribers.Add(eventHandler);
}
}
}
public void Unsubscribe(Action<object, T> eventHandler)
{
lock (lockObject)
{
if (subscribers.Contains(eventHandler))
{
subscribers.Remove(eventHandler);
}
}
}
public virtual void Publish(object sender, T eventArgs)
{
lock (lockObject)
{
for (int i = 0; i < subscribers.Count; i++)
{
subscribers[i](sender, eventArgs);
}
}
}
}
4、事件的基类(有返回值事件的基类,因需要获取返回值,一般采用同步方式调用)
public class MyEventWithResult<T1, T2> : MyEventBase where T1 : EventArgs
{
protected static readonly object lockObject = new object();
protected readonly List<Func<object, T1, T2>> subscribers = new List<Func<object, T1, T2>>();
public void Subscribe(Func<object, T1, T2> eventHandler)
{
lock (lockObject)
{
if (!subscribers.Contains(eventHandler))
{
subscribers.Add(eventHandler);
}
}
}
public void Unsubscribe(Func<object, T1, T2> eventHandler)
{
lock (lockObject)
{
if (subscribers.Contains(eventHandler))
{
subscribers.Remove(eventHandler);
}
}
}
public virtual T2 Publish(object sender, T1 eventArgs)
{
T2 result = default;
lock (lockObject)
{
for (int i = 0; i < subscribers.Count; i++)
{
result = subscribers[i](sender, eventArgs);
}
}
return result;
}
}
5、事件中心,负责自动装载事件
public class MyEventAggregator
{
private static MyEventAggregator _default;
private static readonly object _locker = new object();
private readonly Dictionary<Type, MyEventBase> _eventAggregator = new Dictionary<Type, MyEventBase>();
/// <summary>
/// 默认事件总线实例,建议只使用此实例
/// </summary>
public static MyEventAggregator Default
{
get
{
if (_default == null)
{
lock (_locker)
{
// 如果类的实例不存在则创建,否则直接返回
if (_default == null)
{
_default = new MyEventAggregator();
}
}
}
return _default;
}
}
/// <summary>
/// 构造函数,自动加载EventBase的派生类实现
/// </summary>
public MyEventAggregator()
{
Type type = typeof(MyEventBase);
Assembly assembly = Assembly.GetAssembly(type);
//注册时需排除的基类
Type typeMyEvent = typeof(MyEvent<>);
Type typeMyEventWithResult = typeof(MyEventWithResult<,>);
List<Type> typeList2 = assembly.GetTypes()
.Where(t => t != type && t!=typeAnalysisEvent && t != typeMyEventWithResult && type.IsAssignableFrom(t))
.ToList();
foreach (var item in typeList2)
{
MyEventBase eventBase = (MyEventBase)assembly.CreateInstance(item.FullName);
_eventAggregator.Add(item, eventBase);
}
}
/// <summary>
/// 获取事件实例
/// </summary>
/// <typeparam name="TEvent">事件类型</typeparam>
/// <returns></returns>
public TEvent GetEvent<TEvent>() where TEvent : MyEventBase
{
return (TEvent)_eventAggregator[typeof(TEvent)];
}
/// <summary>
/// 添加事件类型
/// </summary>
/// <typeparam name="TEvent"></typeparam>
public void AddEvent<TEvent>() where TEvent : MyEventBase, new()
{
lock (_locker)
{
Type type = typeof(TEvent);
if (!_eventAggregator.ContainsKey(type))
{
_eventAggregator.Add(type, new TEvent());
}
}
}
/// <summary>
/// 移除事件类型
/// </summary>
/// <typeparam name="TEvent"></typeparam>
public void RemoveEvent<TEvent>() where TEvent : MyEventBase, new()
{
lock (_locker)
{
Type type = typeof(TEvent);
if (_eventAggregator.ContainsKey(type))
{
_eventAggregator.Remove(type);
}
}
}
}
}
6、具体事件的定义和调用示例
定义
/// <summary>
/// 添加日志 事件
/// </summary>
public class WriteLogEvent : MyEvent<WriteLogEventArgs>
{
public override void Publish(object sender, WriteLogEventArgs eventArgs)
{
for (int i = 0; i < subscribers.Count; i++)
{
var action = subscribers[i];
Task.Run(() => action(sender, eventArgs));
}
}
}
public class WriteLogEventArgs : MyEventArgs<WriteLogEventArgs2> { };
public class WriteLogEventArgs2
{
/// <summary>
/// 日志内容
/// </summary>
public string Msg { get; set; }
/// <summary>
/// 操作类型
/// </summary>
public OperationType OperationType { get; set; }
/// <summary>
/// 备注
/// </summary>
public string Remark { get; set; }
/// <summary>
/// 目标类型
/// </summary>
public LogTargetType LogTargetType { get; set; }
/// <summary>
/// 目标值
/// </summary>
public string TargetValue { get; set; }
}
发布事件
MyEventAggregator.Default.GetEvent<WriteLogEvent>().Publish(this, new WriteLogEventArgs
{
Argument = new WriteLogEventArgs2
{
Msg = logMsg,
OperationType = OperationType.Save,
LogTargetType = LogTargetType.OriginalData,
TargetValue = targetValue,
Remark = _MPIComment
}
});
订阅事件
MyEventAggregator.Default.GetEvent<WriteLogEvent>().Subscribe(WriteLogEventHandler);
private void WriteLogEventHandler(object sender, WriteLogEventArgs e)
{
-----business logic
-----
}
本文来自博客园,作者:GIS民工,转载请注明原文链接:https://www.cnblogs.com/kook2007/p/18379352