EventBus.cs 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524
  1. using System;
  2. using System.Collections.Concurrent;
  3. using System.Collections.Generic;
  4. using System.Linq;
  5. using System.Reflection;
  6. using System.Runtime.CompilerServices;
  7. using System.Threading;
  8. using System.Threading.Tasks;
  9. using Abp.Events.Bus.Factories;
  10. using Abp.Events.Bus.Factories.Internals;
  11. using Abp.Events.Bus.Handlers;
  12. using Abp.Events.Bus.Handlers.Internals;
  13. using Abp.Extensions;
  14. using Abp.Threading;
  15. using Abp.Threading.Extensions;
  16. using Castle.Core.Logging;
  17. namespace Abp.Events.Bus
  18. {
  19. /// <summary>
  20. /// Implements EventBus as Singleton pattern.
  21. /// </summary>
  22. public class EventBus : IEventBus
  23. {
  24. /// <summary>
  25. /// Gets the default <see cref="EventBus"/> instance.
  26. /// </summary>
  27. public static EventBus Default { get; } = new EventBus();
  28. /// <summary>
  29. /// Reference to the Logger.
  30. /// </summary>
  31. public ILogger Logger { get; set; }
  32. /// <summary>
  33. /// All registered handler factories.
  34. /// Key: Type of the event
  35. /// Value: List of handler factories
  36. /// </summary>
  37. private readonly ConcurrentDictionary<Type, List<IEventHandlerFactory>> _handlerFactories;
  38. /// <summary>
  39. /// Creates a new <see cref="EventBus"/> instance.
  40. /// Instead of creating a new instace, you can use <see cref="Default"/> to use Global <see cref="EventBus"/>.
  41. /// </summary>
  42. public EventBus()
  43. {
  44. _handlerFactories = new ConcurrentDictionary<Type, List<IEventHandlerFactory>>();
  45. Logger = NullLogger.Instance;
  46. }
  47. /// <inheritdoc/>
  48. public IDisposable Register<TEventData>(Action<TEventData> action) where TEventData : IEventData
  49. {
  50. return Register(typeof(TEventData), new ActionEventHandler<TEventData>(action));
  51. }
  52. /// <inheritdoc/>
  53. public IDisposable AsyncRegister<TEventData>(Func<TEventData, Task> action) where TEventData : IEventData
  54. {
  55. return Register(typeof(TEventData), new AsyncActionEventHandler<TEventData>(action));
  56. }
  57. /// <inheritdoc/>
  58. public IDisposable Register<TEventData>(IEventHandler<TEventData> handler) where TEventData : IEventData
  59. {
  60. return Register(typeof(TEventData), handler);
  61. }
  62. /// <inheritdoc/>
  63. public IDisposable AsyncRegister<TEventData>(IAsyncEventHandler<TEventData> handler) where TEventData : IEventData
  64. {
  65. return Register(typeof(TEventData), handler);
  66. }
  67. /// <inheritdoc/>
  68. public IDisposable Register<TEventData, THandler>()
  69. where TEventData : IEventData
  70. where THandler : IEventHandler, new()
  71. {
  72. return Register(typeof(TEventData), new TransientEventHandlerFactory<THandler>());
  73. }
  74. /// <inheritdoc/>
  75. public IDisposable Register(Type eventType, IEventHandler handler)
  76. {
  77. return Register(eventType, new SingleInstanceHandlerFactory(handler));
  78. }
  79. /// <inheritdoc/>
  80. public IDisposable Register<TEventData>(IEventHandlerFactory factory) where TEventData : IEventData
  81. {
  82. return Register(typeof(TEventData), factory);
  83. }
  84. /// <inheritdoc/>
  85. public IDisposable Register(Type eventType, IEventHandlerFactory factory)
  86. {
  87. GetOrCreateHandlerFactories(eventType)
  88. .Locking(factories => factories.Add(factory));
  89. return new FactoryUnregistrar(this, eventType, factory);
  90. }
  91. /// <inheritdoc/>
  92. public void Unregister<TEventData>(Action<TEventData> action) where TEventData : IEventData
  93. {
  94. Check.NotNull(action, nameof(action));
  95. GetOrCreateHandlerFactories(typeof(TEventData))
  96. .Locking(factories =>
  97. {
  98. factories.RemoveAll(
  99. factory =>
  100. {
  101. var singleInstanceFactory = factory as SingleInstanceHandlerFactory;
  102. if (singleInstanceFactory == null)
  103. {
  104. return false;
  105. }
  106. var actionHandler = singleInstanceFactory.HandlerInstance as ActionEventHandler<TEventData>;
  107. if (actionHandler == null)
  108. {
  109. return false;
  110. }
  111. return actionHandler.Action == action;
  112. });
  113. });
  114. }
  115. /// <inheritdoc/>
  116. public void AsyncUnregister<TEventData>(Func<TEventData, Task> action) where TEventData : IEventData
  117. {
  118. Check.NotNull(action, nameof(action));
  119. GetOrCreateHandlerFactories(typeof(TEventData))
  120. .Locking(factories =>
  121. {
  122. factories.RemoveAll(
  123. factory =>
  124. {
  125. var singleInstanceFactory = factory as SingleInstanceHandlerFactory;
  126. if (singleInstanceFactory == null)
  127. {
  128. return false;
  129. }
  130. var actionHandler = singleInstanceFactory.HandlerInstance as AsyncActionEventHandler<TEventData>;
  131. if (actionHandler == null)
  132. {
  133. return false;
  134. }
  135. return actionHandler.Action == action;
  136. });
  137. });
  138. }
  139. /// <inheritdoc/>
  140. public void Unregister<TEventData>(IEventHandler<TEventData> handler) where TEventData : IEventData
  141. {
  142. Unregister(typeof(TEventData), handler);
  143. }
  144. /// <inheritdoc/>
  145. public void AsyncUnregister<TEventData>(IAsyncEventHandler<TEventData> handler) where TEventData : IEventData
  146. {
  147. Unregister(typeof(TEventData), handler);
  148. }
  149. /// <inheritdoc/>
  150. public void Unregister(Type eventType, IEventHandler handler)
  151. {
  152. GetOrCreateHandlerFactories(eventType)
  153. .Locking(factories =>
  154. {
  155. factories.RemoveAll(
  156. factory =>
  157. factory is SingleInstanceHandlerFactory &&
  158. (factory as SingleInstanceHandlerFactory).HandlerInstance == handler
  159. );
  160. });
  161. }
  162. /// <inheritdoc/>
  163. public void Unregister<TEventData>(IEventHandlerFactory factory) where TEventData : IEventData
  164. {
  165. Unregister(typeof(TEventData), factory);
  166. }
  167. /// <inheritdoc/>
  168. public void Unregister(Type eventType, IEventHandlerFactory factory)
  169. {
  170. GetOrCreateHandlerFactories(eventType).Locking(factories => factories.Remove(factory));
  171. }
  172. /// <inheritdoc/>
  173. public void UnregisterAll<TEventData>() where TEventData : IEventData
  174. {
  175. UnregisterAll(typeof(TEventData));
  176. }
  177. /// <inheritdoc/>
  178. public void UnregisterAll(Type eventType)
  179. {
  180. GetOrCreateHandlerFactories(eventType).Locking(factories => factories.Clear());
  181. }
  182. /// <inheritdoc/>
  183. public void Trigger<TEventData>(TEventData eventData) where TEventData : IEventData
  184. {
  185. Trigger((object)null, eventData);
  186. }
  187. /// <inheritdoc/>
  188. public void Trigger<TEventData>(object eventSource, TEventData eventData) where TEventData : IEventData
  189. {
  190. Trigger(typeof(TEventData), eventSource, eventData);
  191. }
  192. /// <inheritdoc/>
  193. public void Trigger(Type eventType, IEventData eventData)
  194. {
  195. Trigger(eventType, null, eventData);
  196. }
  197. /// <inheritdoc/>
  198. public void Trigger(Type eventType, object eventSource, IEventData eventData)
  199. {
  200. var exceptions = new List<Exception>();
  201. eventData.EventSource = eventSource;
  202. foreach (var handlerFactories in GetHandlerFactories(eventType))
  203. {
  204. foreach (var handlerFactory in handlerFactories.EventHandlerFactories)
  205. {
  206. var handlerType = handlerFactory.GetHandlerType();
  207. if (IsAsyncEventHandler(handlerType))
  208. {
  209. AsyncHelper.RunSync(() => TriggerAsyncHandlingException(handlerFactory, handlerFactories.EventType, eventData, exceptions));
  210. }
  211. else if (IsEventHandler(handlerType))
  212. {
  213. TriggerHandlingException(handlerFactory, handlerFactories.EventType, eventData, exceptions);
  214. }
  215. else
  216. {
  217. var message = $"Event handler to register for event type {eventType.Name} does not implement IEventHandler<{eventType.Name}> or IAsyncEventHandler<{eventType.Name}> interface!";
  218. exceptions.Add(new AbpException(message));
  219. }
  220. }
  221. }
  222. //Implements generic argument inheritance. See IEventDataWithInheritableGenericArgument
  223. if (eventType.GetTypeInfo().IsGenericType &&
  224. eventType.GetGenericArguments().Length == 1 &&
  225. typeof(IEventDataWithInheritableGenericArgument).IsAssignableFrom(eventType))
  226. {
  227. var genericArg = eventType.GetGenericArguments()[0];
  228. var baseArg = genericArg.GetTypeInfo().BaseType;
  229. if (baseArg != null)
  230. {
  231. var baseEventType = eventType.GetGenericTypeDefinition().MakeGenericType(baseArg);
  232. var constructorArgs = ((IEventDataWithInheritableGenericArgument)eventData).GetConstructorArgs();
  233. var baseEventData = (IEventData)Activator.CreateInstance(baseEventType, constructorArgs);
  234. baseEventData.EventTime = eventData.EventTime;
  235. Trigger(baseEventType, eventData.EventSource, baseEventData);
  236. }
  237. }
  238. if (exceptions.Any())
  239. {
  240. if (exceptions.Count == 1)
  241. {
  242. exceptions[0].ReThrow();
  243. }
  244. throw new AggregateException("More than one error has occurred while triggering the event: " + eventType, exceptions);
  245. }
  246. }
  247. /// <inheritdoc/>
  248. public Task TriggerAsync<TEventData>(TEventData eventData) where TEventData : IEventData
  249. {
  250. return TriggerAsync((object)null, eventData);
  251. }
  252. /// <inheritdoc/>
  253. public Task TriggerAsync<TEventData>(object eventSource, TEventData eventData) where TEventData : IEventData
  254. {
  255. return TriggerAsync(typeof(TEventData), eventSource, eventData);
  256. }
  257. /// <inheritdoc/>
  258. public Task TriggerAsync(Type eventType, IEventData eventData)
  259. {
  260. return TriggerAsync(eventType, null, eventData);
  261. }
  262. /// <inheritdoc/>
  263. public async Task TriggerAsync(Type eventType, object eventSource, IEventData eventData)
  264. {
  265. var exceptions = new List<Exception>();
  266. eventData.EventSource = eventSource;
  267. await new SynchronizationContextRemover();
  268. foreach (var handlerFactories in GetHandlerFactories(eventType))
  269. {
  270. foreach (var handlerFactory in handlerFactories.EventHandlerFactories)
  271. {
  272. var handlerType = handlerFactory.GetHandlerType();
  273. if (IsAsyncEventHandler(handlerType))
  274. {
  275. await TriggerAsyncHandlingException(handlerFactory, handlerFactories.EventType, eventData, exceptions);
  276. }
  277. else if (IsEventHandler(handlerType))
  278. {
  279. TriggerHandlingException(handlerFactory, handlerFactories.EventType, eventData, exceptions);
  280. }
  281. else
  282. {
  283. var message = $"Event handler to register for event type {eventType.Name} does not implement IEventHandler<{eventType.Name}> or IAsyncEventHandler<{eventType.Name}> interface!";
  284. exceptions.Add(new AbpException(message));
  285. }
  286. }
  287. }
  288. //Implements generic argument inheritance. See IEventDataWithInheritableGenericArgument
  289. if (eventType.GetTypeInfo().IsGenericType &&
  290. eventType.GetGenericArguments().Length == 1 &&
  291. typeof(IEventDataWithInheritableGenericArgument).IsAssignableFrom(eventType))
  292. {
  293. var genericArg = eventType.GetGenericArguments()[0];
  294. var baseArg = genericArg.GetTypeInfo().BaseType;
  295. if (baseArg != null)
  296. {
  297. var baseEventType = eventType.GetGenericTypeDefinition().MakeGenericType(baseArg);
  298. var constructorArgs = ((IEventDataWithInheritableGenericArgument)eventData).GetConstructorArgs();
  299. var baseEventData = (IEventData)Activator.CreateInstance(baseEventType, constructorArgs);
  300. baseEventData.EventTime = eventData.EventTime;
  301. await TriggerAsync(baseEventType, eventData.EventSource, baseEventData);
  302. }
  303. }
  304. if (exceptions.Any())
  305. {
  306. if (exceptions.Count == 1)
  307. {
  308. exceptions[0].ReThrow();
  309. }
  310. throw new AggregateException("More than one error has occurred while triggering the event: " + eventType, exceptions);
  311. }
  312. }
  313. private void TriggerHandlingException(IEventHandlerFactory handlerFactory, Type eventType, IEventData eventData, List<Exception> exceptions)
  314. {
  315. var eventHandler = handlerFactory.GetHandler();
  316. try
  317. {
  318. if (eventHandler == null)
  319. {
  320. throw new ArgumentNullException($"Registered event handler for event type {eventType.Name} is null!");
  321. }
  322. var handlerType = typeof(IEventHandler<>).MakeGenericType(eventType);
  323. var method = handlerType.GetMethod(
  324. "HandleEvent",
  325. new[] { eventType }
  326. );
  327. method.Invoke(eventHandler, new object[] { eventData });
  328. }
  329. catch (TargetInvocationException ex)
  330. {
  331. exceptions.Add(ex.InnerException);
  332. }
  333. catch (Exception ex)
  334. {
  335. exceptions.Add(ex);
  336. }
  337. finally
  338. {
  339. handlerFactory.ReleaseHandler(eventHandler);
  340. }
  341. }
  342. private async Task TriggerAsyncHandlingException(IEventHandlerFactory asyncHandlerFactory, Type eventType, IEventData eventData, List<Exception> exceptions)
  343. {
  344. var asyncEventHandler = asyncHandlerFactory.GetHandler();
  345. try
  346. {
  347. if (asyncEventHandler == null)
  348. {
  349. throw new ArgumentNullException($"Registered async event handler for event type {eventType.Name} is null!");
  350. }
  351. var asyncHandlerType = typeof(IAsyncEventHandler<>).MakeGenericType(eventType);
  352. var method = asyncHandlerType.GetMethod(
  353. "HandleEventAsync",
  354. new[] { eventType }
  355. );
  356. await (Task)method.Invoke(asyncEventHandler, new object[] { eventData });
  357. }
  358. catch (TargetInvocationException ex)
  359. {
  360. exceptions.Add(ex.InnerException);
  361. }
  362. catch (Exception ex)
  363. {
  364. exceptions.Add(ex);
  365. }
  366. finally
  367. {
  368. asyncHandlerFactory.ReleaseHandler(asyncEventHandler);
  369. }
  370. }
  371. private bool IsEventHandler(Type handlerType)
  372. {
  373. return handlerType.GetInterfaces()
  374. .Where(i => i.IsGenericType)
  375. .Any(i => i.GetGenericTypeDefinition() == typeof(IEventHandler<>));
  376. }
  377. private bool IsAsyncEventHandler(Type handlerType)
  378. {
  379. return handlerType.GetInterfaces()
  380. .Where(i => i.IsGenericType)
  381. .Any(i => i.GetGenericTypeDefinition() == typeof(IAsyncEventHandler<>));
  382. }
  383. private IEnumerable<EventTypeWithEventHandlerFactories> GetHandlerFactories(Type eventType)
  384. {
  385. var handlerFactoryList = new List<EventTypeWithEventHandlerFactories>();
  386. foreach (var handlerFactory in _handlerFactories.Where(hf => ShouldTriggerEventForHandler(eventType, hf.Key)))
  387. {
  388. handlerFactoryList.Add(new EventTypeWithEventHandlerFactories(handlerFactory.Key, handlerFactory.Value));
  389. }
  390. return handlerFactoryList.ToArray();
  391. }
  392. private static bool ShouldTriggerEventForHandler(Type eventType, Type handlerType)
  393. {
  394. //Should trigger same type
  395. if (handlerType == eventType)
  396. {
  397. return true;
  398. }
  399. //Should trigger for inherited types
  400. if (handlerType.IsAssignableFrom(eventType))
  401. {
  402. return true;
  403. }
  404. return false;
  405. }
  406. private List<IEventHandlerFactory> GetOrCreateHandlerFactories(Type eventType)
  407. {
  408. return _handlerFactories.GetOrAdd(eventType, (type) => new List<IEventHandlerFactory>());
  409. }
  410. private class EventTypeWithEventHandlerFactories
  411. {
  412. public Type EventType { get; }
  413. public List<IEventHandlerFactory> EventHandlerFactories { get; }
  414. public EventTypeWithEventHandlerFactories(Type eventType, List<IEventHandlerFactory> eventHandlerFactories)
  415. {
  416. EventType = eventType;
  417. EventHandlerFactories = eventHandlerFactories;
  418. }
  419. }
  420. // Reference from
  421. // https://blogs.msdn.microsoft.com/benwilli/2017/02/09/an-alternative-to-configureawaitfalse-everywhere/
  422. private struct SynchronizationContextRemover : INotifyCompletion
  423. {
  424. public bool IsCompleted
  425. {
  426. get { return SynchronizationContext.Current == null; }
  427. }
  428. public void OnCompleted(Action continuation)
  429. {
  430. var prevContext = SynchronizationContext.Current;
  431. try
  432. {
  433. SynchronizationContext.SetSynchronizationContext(null);
  434. continuation();
  435. }
  436. finally
  437. {
  438. SynchronizationContext.SetSynchronizationContext(prevContext);
  439. }
  440. }
  441. public SynchronizationContextRemover GetAwaiter()
  442. {
  443. return this;
  444. }
  445. public void GetResult()
  446. {
  447. }
  448. }
  449. }
  450. }