/src/Extensions/SimpleCqrs.NServiceBus.Core/Eventing/NsbLocalEventBus.cs

https://github.com/kristofferahl/SimpleCQRS
C# | 101 lines | 87 code | 14 blank | 0 comment | 5 complexity | e3472fd60345d0b892ae1d81f9470cfd MD5 | raw file
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using log4net;
  5. using SimpleCqrs.Eventing;
  6. namespace SimpleCqrs.NServiceBus.Eventing
  7. {
  8. internal class NsbLocalEventBus : IEventBus
  9. {
  10. private readonly IDomainEventHandlerFactory eventHandlerBuilder;
  11. private IDictionary<Type, EventHandlerInvoker> eventHandlerInvokers;
  12. public NsbLocalEventBus(IEnumerable<Type> eventHandlerTypes, IDomainEventHandlerFactory eventHandlerBuilder)
  13. {
  14. this.eventHandlerBuilder = eventHandlerBuilder;
  15. BuildEventInvokers(eventHandlerTypes);
  16. }
  17. public void PublishEvent(DomainEvent domainEvent)
  18. {
  19. if(!eventHandlerInvokers.ContainsKey(domainEvent.GetType())) return;
  20. var eventHandlerInvoker = eventHandlerInvokers[domainEvent.GetType()];
  21. eventHandlerInvoker.Publish(domainEvent);
  22. }
  23. public void PublishEvents(IEnumerable<DomainEvent> domainEvents)
  24. {
  25. foreach(var domainEvent in domainEvents)
  26. PublishEvent(domainEvent);
  27. }
  28. private void BuildEventInvokers(IEnumerable<Type> eventHandlerTypes)
  29. {
  30. eventHandlerInvokers = new Dictionary<Type, EventHandlerInvoker>();
  31. foreach(var eventHandlerType in eventHandlerTypes)
  32. {
  33. foreach(var domainEventType in GetDomainEventTypes(eventHandlerType))
  34. {
  35. EventHandlerInvoker eventInvoker;
  36. if(!eventHandlerInvokers.TryGetValue(domainEventType, out eventInvoker))
  37. eventInvoker = new EventHandlerInvoker(eventHandlerBuilder, domainEventType);
  38. eventInvoker.AddEventHandlerType(eventHandlerType);
  39. eventHandlerInvokers[domainEventType] = eventInvoker;
  40. }
  41. }
  42. }
  43. private static IEnumerable<Type> GetDomainEventTypes(Type eventHandlerType)
  44. {
  45. return from interfaceType in eventHandlerType.GetInterfaces()
  46. where interfaceType.IsGenericType && interfaceType.GetGenericTypeDefinition() == typeof(IHandleDomainEvents<>)
  47. select interfaceType.GetGenericArguments()[0];
  48. }
  49. private class EventHandlerInvoker
  50. {
  51. private readonly IDomainEventHandlerFactory eventHandlerFactory;
  52. private readonly Type domainEventType;
  53. private readonly List<Type> eventHandlerTypes;
  54. private readonly ILog logger = LogManager.GetLogger(typeof(NsbLocalEventBus));
  55. public EventHandlerInvoker(IDomainEventHandlerFactory eventHandlerFactory, Type domainEventType)
  56. {
  57. this.eventHandlerFactory = eventHandlerFactory;
  58. this.domainEventType = domainEventType;
  59. eventHandlerTypes = new List<Type>();
  60. }
  61. public void AddEventHandlerType(Type eventHandlerType)
  62. {
  63. eventHandlerTypes.Add(eventHandlerType);
  64. }
  65. public void Publish(DomainEvent domainEvent)
  66. {
  67. var exceptionList = new List<Exception>();
  68. var handleMethod = typeof(IHandleDomainEvents<>).MakeGenericType(domainEventType).GetMethod("Handle");
  69. foreach(var eventHandlerType in eventHandlerTypes)
  70. {
  71. try
  72. {
  73. var eventHandler = eventHandlerFactory.Create(eventHandlerType);
  74. handleMethod.Invoke(eventHandler, new object[] {domainEvent});
  75. }
  76. catch(Exception exception)
  77. {
  78. logger.Error(string.Format("An exception occured while handling event of type '{0}'\nMessage: {1}", domainEvent.GetType(), exception.Message), exception);
  79. exceptionList.Add(exception);
  80. }
  81. }
  82. if(exceptionList.Count > 0)
  83. throw new AggregateException(exceptionList);
  84. }
  85. }
  86. }
  87. }