using System;
using System.Collections.Generic;
using System.Linq;
namespace CRM.Core.Common.EventBus
{
///
/// 事件总线
/// 发布与订阅处理逻辑
/// 核心功能代码
///
public class EventBus
{
private EventBus() { }
private static EventBus _eventBus = null;
private readonly object sync = new object();
///
/// 对于事件数据的存储,目前采用内存字典
///
private static Dictionary> eventHandlers = new Dictionary>();
///
// checks if the two event handlers are equal. if the event handler is an action-delegated, just simply
// compare the two with the object.Equals override (since it was overriden by comparing the two delegates. Otherwise,
// the type of the event handler will be used because we don't need to register the same type of the event handler
// more than once for each specific event.
///
private readonly Func eventHandlerEquals = (o1, o2) =>
{
var o1Type = o1.GetType();
var o2Type = o2.GetType();
if (o1Type.IsGenericType &&
o1Type.GetGenericTypeDefinition() == typeof(ActionDelegatedEventHandler<>) &&
o2Type.IsGenericType &&
o2Type.GetGenericTypeDefinition() == typeof(ActionDelegatedEventHandler<>))
return o1.Equals(o2);
return o1Type == o2Type;
};
///
/// 初始化空的事件总件
///
public static EventBus Instance
{
get
{
return _eventBus ?? (_eventBus = new EventBus());
}
}
#region 事件订阅&取消订阅,可以扩展
///
/// 订阅事件列表
///
///
///
public void Subscribe(IEventHandler eventHandler)
where TEvent : class, IEvent
{
lock (sync)
{
var eventType = typeof(TEvent);
if (eventHandlers.ContainsKey(eventType))
{
var handlers = eventHandlers[eventType];
if (handlers != null)
{
if (!handlers.Exists(deh => eventHandlerEquals(deh, eventHandler)))
handlers.Add(eventHandler);
}
else
{
handlers = new List();
handlers.Add(eventHandler);
}
}
else
eventHandlers.Add(eventType, new List { eventHandler });
}
}
///
/// 订阅事件实体
///
///
///
public void Subscribe(Action eventHandlerFunc)
where TEvent : class, IEvent
{
Subscribe(new ActionDelegatedEventHandler(eventHandlerFunc));
}
public void Subscribe(IEnumerable> eventHandlers)
where TEvent : class, IEvent
{
foreach (var eventHandler in eventHandlers)
Subscribe(eventHandler);
}
///
/// 取消订阅事件
///
///
///
public void Unsubscribe(IEventHandler eventHandler)
where TEvent : class, IEvent
{
lock (sync)
{
var eventType = typeof(TEvent);
if (eventHandlers.ContainsKey(eventType))
{
var handlers = eventHandlers[eventType];
if (handlers != null
&& handlers.Exists(deh => eventHandlerEquals(deh, eventHandler)))
{
var handlerToRemove = handlers.First(deh => eventHandlerEquals(deh, eventHandler));
handlers.Remove(handlerToRemove);
}
}
}
}
public void Unsubscribe(IEnumerable> eventHandlers)
where TEvent : class, IEvent
{
foreach (var eventHandler in eventHandlers)
Unsubscribe(eventHandler);
}
public void Unsubscribe(Action eventHandlerFunc)
where TEvent : class, IEvent
{
Unsubscribe(new ActionDelegatedEventHandler(eventHandlerFunc));
}
#endregion
#region 事件发布
///
/// 发布事件,支持异步事件
///
///
///
public void Publish(TEvent evnt)
where TEvent : class, IEvent
{
if (evnt == null)
throw new ArgumentNullException("evnt");
var eventType = evnt.GetType();
if (eventHandlers.ContainsKey(eventType)
&& eventHandlers[eventType] != null
&& eventHandlers[eventType].Count > 0)
{
var handlers = eventHandlers[eventType];
foreach (var handler in handlers)
{
var eventHandler = handler as IEventHandler;
eventHandler.Handle(evnt);
}
}
else
{
WX.CRM.Common.LogHelper.Info("天真根本找不到!" + eventType.Name);
}
}
public void Publish(TEvent evnt, Action callback, TimeSpan? timeout = null)
where TEvent : class, IEvent
{
if (evnt == null)
throw new ArgumentNullException("evnt");
var eventType = evnt.GetType();
if (eventHandlers.ContainsKey(eventType) &&
eventHandlers[eventType] != null &&
eventHandlers[eventType].Count > 0)
{
var handlers = eventHandlers[eventType];
try
{
foreach (var handler in handlers)
{
var eventHandler = handler as IEventHandler;
eventHandler.Handle(evnt);
callback(evnt, true, null);
}
}
catch (Exception ex)
{
callback(evnt, false, ex);
}
}
else
callback(evnt, false, null);
}
#endregion
}
}