usingSystem;usingSystem.Collections.Generic;usingSystem.Linq;usingSystem.Reflection;usingSystem.Text;usingSystem.Threading.Tasks;namespaceKeasy5.Events
{public classEventAggregator : IEventAggregator
{#region private property
private readonly object sync = new object();private readonly Dictionary> eventHandlers = new Dictionary>();private readonlyMethodInfo registerEventHandlerMethod;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<>))returno1.Equals(o2);return o1Type ==o2Type;
};//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.
#endregion
#region Ctor
publicEventAggregator()
{
registerEventHandlerMethod= (from p in this.GetType().GetMethods()
let methodName=p.Name
let parameters=p.GetParameters()where methodName == "Subscribe" &¶meters!= null &¶meters.Length== 1 &¶meters[0].ParameterType.GetGenericTypeDefinition() == typeof(IEventHandler<>)selectp).First();
}///
///
///
///
///
///1.相关资料:C# 反射泛型/// http://www.cnblogs.com/easy5weikai/p/3790589.html
///2. 依赖注入:///
///
///
///
///
///
///
///
///
///
///
///
public EventAggregator(object[] handlers)
:this()
{foreach (var obj inhandlers)
{var type =obj.GetType();var implementedInterfaces =type.GetInterfaces();foreach (var implementedInterface inimplementedInterfaces)
{if (implementedInterface.IsGenericType &&implementedInterface.GetGenericTypeDefinition()== typeof(IEventHandler<>))
{var eventType =implementedInterface.GetGenericArguments().First();var method =registerEventHandlerMethod.MakeGenericMethod(eventType);
method.Invoke(this, new object[] { obj });
}
}
}
}#endregion
#region interface IEventAggregator members
public void Subscribe(IEventHandlereventHandler)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);
}
}elseeventHandlers.Add(eventType,new List{ eventHandler });
}
}public void Subscribe(IEnumerable>eventHandlers)where TEvent : class, IEvent
{foreach (var eventHandler ineventHandlers)
Subscribe(eventHandler);
}public void Subscribe(params IEventHandler[] eventHandlers)where TEvent : class, IEvent
{foreach (var eventHandler ineventHandlers)
Subscribe(eventHandler);
}public void Subscribe(ActioneventHandlerFunc)where TEvent : class, IEvent
{
Subscribe(new ActionDelegatedEventHandler(eventHandlerFunc));
}public void Subscribe(IEnumerable>eventHandlerFuncs)where TEvent : class, IEvent
{foreach (var eventHandlerFunc ineventHandlerFuncs)
Subscribe(eventHandlerFunc);
}public void Subscribe(params Func[] eventHandlerFuncs)where TEvent : class, IEvent
{foreach (var eventHandlerFunc ineventHandlerFuncs)
Subscribe(eventHandlerFunc);
}public void Unsubscribe(IEventHandlereventHandler)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 ineventHandlers)
Unsubscribe(eventHandler);
}public void Unsubscribe(params IEventHandler[] eventHandlers)where TEvent : class, IEvent
{foreach (var eventHandler ineventHandlers)
Unsubscribe(eventHandler);
}public void Unsubscribe(ActioneventHandlerFunc)where TEvent : class, IEvent
{
Unsubscribe(new ActionDelegatedEventHandler(eventHandlerFunc));
}public void Unsubscribe(IEnumerable>eventHandlerFuncs)where TEvent : class, IEvent
{foreach (var eventHandlerFunc ineventHandlerFuncs)
Unsubscribe(eventHandlerFunc);
}public void Unsubscribe(params Func[] eventHandlerFuncs)where TEvent : class, IEvent
{foreach (var eventHandlerFunc ineventHandlerFuncs)
Unsubscribe(eventHandlerFunc);
}public void UnsubscribeAll()where TEvent : class, IEvent
{lock(sync)
{var eventType = typeof(TEvent);if(eventHandlers.ContainsKey(eventType))
{var handlers =eventHandlers[eventType];if (handlers != null)
handlers.Clear();
}
}
}public voidUnsubscribeAll()
{lock(sync)
{
eventHandlers.Clear();
}
}public IEnumerable> GetSubscriptions()where TEvent : class, IEvent
{var eventType = typeof(TEvent);if(eventHandlers.ContainsKey(eventType))
{var handlers =eventHandlers[eventType];if (handlers != null)return handlers.Select(p => p as IEventHandler).ToList();else
return null;
}else
return null;
}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 inhandlers)
{var eventHandler = handler as IEventHandler;if (eventHandler == null)throw new ArgumentNullException("eventHandler");if (eventHandler.GetType().IsDefined(typeof(HandlesAsynchronouslyAttribute), false))
{
Task.Factory.StartNew((o)=>eventHandler.Handle((TEvent)o), evnt);
}else{
eventHandler.Handle(evnt);
}
}
}
}public void Publish(TEvent evnt,
Actioncallback,
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];
List tasks = new List();try{foreach (var handler inhandlers)
{var eventHandler = handler as IEventHandler;if (eventHandler.GetType().IsDefined(typeof(HandlesAsynchronouslyAttribute), false))
{
tasks.Add(Task.Factory.StartNew((o)=>eventHandler.Handle((TEvent)o), evnt));
}else{
eventHandler.Handle(evnt);
}
}if (tasks.Count > 0)
{if (timeout == null)
Task.WaitAll(tasks.ToArray());elseTask.WaitAll(tasks.ToArray(), timeout.Value);
}
callback(evnt,true, null);
}catch(Exception ex)
{
callback(evnt,false, ex);
}
}elsecallback(evnt,false, null);
}#endregion}
}