Browse Source

Renamed IEventBus to ILocalEventBus and introduced IDistributedEventBus

pull/594/head
Halil ibrahim Kalkan 8 years ago
parent
commit
f440446254
  1. 11
      framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/Events/EntityChangeEventHelper.cs
  2. 35
      framework/src/Volo.Abp.EventBus.Distributed.RabbitMQ/Volo/Abp/EventBus/Distributed/RabbitMq/RabbitMqDistributedEventBus.cs
  3. 64
      framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Distributed/IDistributedEventBus.cs
  4. 59
      framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Distributed/LocalDistributedEventBus.cs
  5. 2
      framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/EventHandlerFactoryUnregistrar.cs
  6. 126
      framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/IEventBus.cs
  7. 25
      framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/IEventPublisher.cs
  8. 111
      framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/IEventSubscriber.cs
  9. 10
      framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Local/ILocalEventBus.cs
  10. 156
      framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Local/LocalEventBus.cs
  11. 90
      framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/NullEventBus.cs
  12. 91
      framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/NullLocalEventBus.cs
  13. 7
      framework/src/Volo.Abp.MongoDB/Volo/Abp/Domain/Repositories/MongoDB/MongoDbRepository.cs
  14. 17
      framework/test/Volo.Abp.EventBus.Tests/Volo/Abp/EventBus/Distributed/LocalDistributedEventBusTestBase.cs
  15. 21
      framework/test/Volo.Abp.EventBus.Tests/Volo/Abp/EventBus/Distributed/LocalDistributedEventBus_Test.cs
  16. 23
      framework/test/Volo.Abp.EventBus.Tests/Volo/Abp/EventBus/Distributed/MySimpleDistributedTransientEventHandler.cs
  17. 48
      framework/test/Volo.Abp.EventBus.Tests/Volo/Abp/EventBus/InheritanceTest.cs
  18. 54
      framework/test/Volo.Abp.EventBus.Tests/Volo/Abp/EventBus/Local/ActionBasedEventHandlerTest.cs
  19. 6
      framework/test/Volo.Abp.EventBus.Tests/Volo/Abp/EventBus/Local/EventBusTestBase.cs
  20. 10
      framework/test/Volo.Abp.EventBus.Tests/Volo/Abp/EventBus/Local/EventBus_DI_Services_Test.cs
  21. 12
      framework/test/Volo.Abp.EventBus.Tests/Volo/Abp/EventBus/Local/EventBus_Exception_Test.cs
  22. 8
      framework/test/Volo.Abp.EventBus.Tests/Volo/Abp/EventBus/Local/EventBus_MultipleHandle_Test.cs
  23. 10
      framework/test/Volo.Abp.EventBus.Tests/Volo/Abp/EventBus/Local/GenericInheritanceTest.cs
  24. 48
      framework/test/Volo.Abp.EventBus.Tests/Volo/Abp/EventBus/Local/InheritanceTest.cs
  25. 2
      framework/test/Volo.Abp.EventBus.Tests/Volo/Abp/EventBus/Local/MySimpleEventDataHandler.cs
  26. 2
      framework/test/Volo.Abp.EventBus.Tests/Volo/Abp/EventBus/Local/MySimpleTransientEventHandler.cs
  27. 10
      framework/test/Volo.Abp.EventBus.Tests/Volo/Abp/EventBus/Local/TransientDisposableEventHandlerTest.cs
  28. 7
      framework/test/Volo.Abp.TestApp/Volo/Abp/TestApp/Testing/DomainEvents_Tests.cs
  29. 13
      framework/test/Volo.Abp.TestApp/Volo/Abp/TestApp/Testing/EntityChangeEvents_Tests.cs

11
framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/Events/EntityChangeEventHelper.cs

@ -5,6 +5,7 @@ using Volo.Abp.Auditing;
using Volo.Abp.DependencyInjection;
using Volo.Abp.DynamicProxy;
using Volo.Abp.EventBus;
using Volo.Abp.EventBus.Local;
using Volo.Abp.Uow;
namespace Volo.Abp.Domain.Entities.Events
@ -14,14 +15,14 @@ namespace Volo.Abp.Domain.Entities.Events
/// </summary>
public class EntityChangeEventHelper : IEntityChangeEventHelper, ITransientDependency
{
public IEventBus EventBus { get; set; }
public ILocalEventBus LocalEventBus { get; set; }
private readonly IUnitOfWorkManager _unitOfWorkManager;
public EntityChangeEventHelper(IUnitOfWorkManager unitOfWorkManager)
{
_unitOfWorkManager = unitOfWorkManager;
EventBus = NullEventBus.Instance;
LocalEventBus = NullLocalEventBus.Instance;
}
public async Task TriggerEventsAsync(EntityChangeReport changeReport)
@ -115,7 +116,7 @@ namespace Volo.Abp.Domain.Entities.Events
{
foreach (var domainEvent in domainEvents)
{
await EventBus.TriggerAsync(domainEvent.EventData.GetType(), domainEvent.EventData);
await LocalEventBus.PublishAsync(domainEvent.EventData.GetType(), domainEvent.EventData);
}
}
@ -126,11 +127,11 @@ namespace Volo.Abp.Domain.Entities.Events
if (triggerInCurrentUnitOfWork || _unitOfWorkManager.Current == null)
{
await EventBus.TriggerAsync(eventType, Activator.CreateInstance(eventType, entity));
await LocalEventBus.PublishAsync(eventType, Activator.CreateInstance(eventType, entity));
return;
}
_unitOfWorkManager.Current.OnCompleted(() => EventBus.TriggerAsync(eventType, Activator.CreateInstance(eventType, entity)));
_unitOfWorkManager.Current.OnCompleted(() => LocalEventBus.PublishAsync(eventType, Activator.CreateInstance(eventType, entity)));
}
}
}

35
framework/src/Volo.Abp.EventBus.Distributed.RabbitMQ/Volo/Abp/EventBus/Distributed/RabbitMq/RabbitMqDistributedEventBus.cs

@ -57,6 +57,41 @@ namespace Volo.Abp.EventBus.Distributed.RabbitMq
throw new NotImplementedException();
}
public void Unsubscribe<TEvent>(Func<TEvent, Task> action) where TEvent : class
{
throw new NotImplementedException();
}
public void Unsubscribe<TEvent>(IEventHandler<TEvent> handler) where TEvent : class
{
throw new NotImplementedException();
}
public void Unsubscribe(Type eventType, IEventHandler handler)
{
throw new NotImplementedException();
}
public void Unsubscribe<TEvent>(IEventHandlerFactory factory) where TEvent : class
{
throw new NotImplementedException();
}
public void Unsubscribe(Type eventType, IEventHandlerFactory factory)
{
throw new NotImplementedException();
}
public void UnsubscribeAll<TEvent>() where TEvent : class
{
throw new NotImplementedException();
}
public void UnsubscribeAll(Type eventType)
{
throw new NotImplementedException();
}
public Task PublishAsync<TEvent>(TEvent eventData)
where TEvent : class
{

64
framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Distributed/IDistributedEventBus.cs

@ -1,65 +1,7 @@
using System;
using System.Threading.Tasks;
namespace Volo.Abp.EventBus.Distributed
namespace Volo.Abp.EventBus.Distributed
{
public interface IDistributedEventBus
public interface IDistributedEventBus : IEventBus
{
/// <summary>
/// Subscribes to an event.
/// Given action is called for all event occurrences.
/// </summary>
/// <param name="action">Action to handle events</param>
/// <typeparam name="TEvent">Event type</typeparam>
IDisposable Subscribe<TEvent>(Func<TEvent, Task> action)
where TEvent : class;
/// <summary>
/// Subscribes to an event.
/// Same (given) instance of the handler is used for all event occurrences.
/// </summary>
/// <typeparam name="TEvent">Event type</typeparam>
/// <param name="handler">Object to handle the event</param>
IDisposable Subscribe<TEvent>(IEventHandler<TEvent> handler)
where TEvent : class;
/// <summary>
/// Subscribes to an event.
/// A new instance of <see cref="THandler"/> object is created for every event occurrence.
/// </summary>
/// <typeparam name="TEvent">Event type</typeparam>
/// <typeparam name="THandler">Type of the event handler</typeparam>
IDisposable Subscribe<TEvent, THandler>()
where TEvent : class
where THandler : IEventHandler, new();
/// <summary>
/// Subscribes to an event.
/// Same (given) instance of the handler is used for all event occurrences.
/// </summary>
/// <param name="eventType">Event type</param>
/// <param name="handler">Object to handle the event</param>
IDisposable Subscribe(Type eventType, IEventHandler handler);
/// <summary>
/// Subscribes to an event.
/// Given factory is used to create/release handlers
/// </summary>
/// <typeparam name="TEvent">Event type</typeparam>
/// <param name="factory">A factory to create/release handlers</param>
IDisposable Subscribe<TEvent>(IEventHandlerFactory factory)
where TEvent : class;
/// <summary>
/// Subscribes to an event.
/// </summary>
/// <param name="eventType">Event type</param>
/// <param name="factory">A factory to create/release handlers</param>
IDisposable Subscribe(Type eventType, IEventHandlerFactory factory);
Task PublishAsync<TEvent>(TEvent eventData)
where TEvent : class;
Task PublishAsync(Type eventType, object eventData);
}
}

59
framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Distributed/LocalDistributedEventBus.cs

@ -1,58 +1,95 @@
using System;
using System.Threading.Tasks;
using Volo.Abp.DependencyInjection;
using Volo.Abp.EventBus.Local;
namespace Volo.Abp.EventBus.Distributed
{
[Dependency(TryRegister = true)]
[ExposeServices(typeof(IDistributedEventBus), typeof(LocalDistributedEventBus))]
public class LocalDistributedEventBus : IDistributedEventBus, ITransientDependency
{
private readonly IEventBus _eventBus;
private readonly ILocalEventBus _localEventBus;
public LocalDistributedEventBus(IEventBus eventBus)
public LocalDistributedEventBus(ILocalEventBus localEventBus)
{
_eventBus = eventBus;
_localEventBus = localEventBus;
}
public IDisposable Subscribe<TEvent>(Func<TEvent, Task> action) where TEvent : class
{
return _eventBus.Register(action);
return _localEventBus.Subscribe(action);
}
public IDisposable Subscribe<TEvent>(IEventHandler<TEvent> handler) where TEvent : class
{
return _eventBus.Register(handler);
return _localEventBus.Subscribe(handler);
}
public IDisposable Subscribe<TEvent, THandler>() where TEvent : class where THandler : IEventHandler, new()
{
return _eventBus.Register<TEvent, THandler>();
return _localEventBus.Subscribe<TEvent, THandler>();
}
public IDisposable Subscribe(Type eventType, IEventHandler handler)
{
return _eventBus.Register(eventType, handler);
return _localEventBus.Subscribe(eventType, handler);
}
public IDisposable Subscribe<TEvent>(IEventHandlerFactory factory) where TEvent : class
{
return _eventBus.Register<TEvent>(factory);
return _localEventBus.Subscribe<TEvent>(factory);
}
public IDisposable Subscribe(Type eventType, IEventHandlerFactory factory)
{
return _eventBus.Register(eventType, factory);
return _localEventBus.Subscribe(eventType, factory);
}
public void Unsubscribe<TEvent>(Func<TEvent, Task> action) where TEvent : class
{
_localEventBus.Unsubscribe(action);
}
public void Unsubscribe<TEvent>(IEventHandler<TEvent> handler) where TEvent : class
{
_localEventBus.Unsubscribe(handler);
}
public void Unsubscribe(Type eventType, IEventHandler handler)
{
_localEventBus.Unsubscribe(eventType, handler);
}
public void Unsubscribe<TEvent>(IEventHandlerFactory factory) where TEvent : class
{
_localEventBus.Unsubscribe<TEvent>(factory);
}
public void Unsubscribe(Type eventType, IEventHandlerFactory factory)
{
_localEventBus.Unsubscribe(eventType, factory);
}
public void UnsubscribeAll<TEvent>() where TEvent : class
{
_localEventBus.UnsubscribeAll<TEvent>();
}
public void UnsubscribeAll(Type eventType)
{
_localEventBus.UnsubscribeAll(eventType);
}
public Task PublishAsync<TEvent>(TEvent eventData)
where TEvent : class
{
return _eventBus.TriggerAsync(eventData);
return _localEventBus.PublishAsync(eventData);
}
public Task PublishAsync(Type eventType, object eventData)
{
return _eventBus.TriggerAsync(eventType, eventData);
return _localEventBus.PublishAsync(eventType, eventData);
}
}
}

2
framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/EventHandlerFactoryUnregistrar.cs

@ -20,7 +20,7 @@ namespace Volo.Abp.EventBus
public void Dispose()
{
_eventBus.Unregister(_eventType, _factory);
_eventBus.Unsubscribe(_eventType, _factory);
}
}
}

126
framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/IEventBus.cs

@ -1,131 +1,7 @@
using System;
using System.Threading.Tasks;
namespace Volo.Abp.EventBus
{
/// <summary>
/// Defines interface of the event bus.
/// </summary>
public interface IEventBus
public interface IEventBus : IEventSubscriber, IEventPublisher
{
/// <summary>
/// Registers to an event.
/// Given action is called for all event occurrences.
/// </summary>
/// <param name="action">Action to handle events</param>
/// <typeparam name="TEvent">Event type</typeparam>
IDisposable Register<TEvent>(Func<TEvent, Task> action)
where TEvent : class;
/// <summary>
/// Registers to an event.
/// Same (given) instance of the handler is used for all event occurrences.
/// </summary>
/// <typeparam name="TEvent">Event type</typeparam>
/// <param name="handler">Object to handle the event</param>
IDisposable Register<TEvent>(IEventHandler<TEvent> handler)
where TEvent : class;
/// <summary>
/// Registers to an event.
/// A new instance of <see cref="THandler"/> object is created for every event occurrence.
/// </summary>
/// <typeparam name="TEvent">Event type</typeparam>
/// <typeparam name="THandler">Type of the event handler</typeparam>
IDisposable Register<TEvent, THandler>()
where TEvent : class
where THandler : IEventHandler, new();
/// <summary>
/// Registers to an event.
/// Same (given) instance of the handler is used for all event occurrences.
/// </summary>
/// <param name="eventType">Event type</param>
/// <param name="handler">Object to handle the event</param>
IDisposable Register(Type eventType, IEventHandler handler);
/// <summary>
/// Registers to an event.
/// Given factory is used to create/release handlers
/// </summary>
/// <typeparam name="TEvent">Event type</typeparam>
/// <param name="factory">A factory to create/release handlers</param>
IDisposable Register<TEvent>(IEventHandlerFactory factory)
where TEvent : class;
/// <summary>
/// Registers to an event.
/// </summary>
/// <param name="eventType">Event type</param>
/// <param name="factory">A factory to create/release handlers</param>
IDisposable Register(Type eventType, IEventHandlerFactory factory);
/// <summary>
/// Unregisters from an event.
/// </summary>
/// <typeparam name="TEvent">Event type</typeparam>
/// <param name="action"></param>
void Unregister<TEvent>(Func<TEvent, Task> action)
where TEvent : class;
/// <summary>
/// Unregisters from an event.
/// </summary>
/// <typeparam name="TEvent">Event type</typeparam>
/// <param name="handler">Handler object that is registered before</param>
void Unregister<TEvent>(IEventHandler<TEvent> handler)
where TEvent : class;
/// <summary>
/// Unregisters from an event.
/// </summary>
/// <param name="eventType">Event type</param>
/// <param name="handler">Handler object that is registered before</param>
void Unregister(Type eventType, IEventHandler handler);
/// <summary>
/// Unregisters from an event.
/// </summary>
/// <typeparam name="TEvent">Event type</typeparam>
/// <param name="factory">Factory object that is registered before</param>
void Unregister<TEvent>(IEventHandlerFactory factory)
where TEvent : class;
/// <summary>
/// Unregisters from an event.
/// </summary>
/// <param name="eventType">Event type</param>
/// <param name="factory">Factory object that is registered before</param>
void Unregister(Type eventType, IEventHandlerFactory factory);
/// <summary>
/// Unregisters all event handlers of given event type.
/// </summary>
/// <typeparam name="TEvent">Event type</typeparam>
void UnregisterAll<TEvent>()
where TEvent : class;
/// <summary>
/// Unregisters all event handlers of given event type.
/// </summary>
/// <param name="eventType">Event type</param>
void UnregisterAll(Type eventType);
/// <summary>
/// Triggers an event asynchronously.
/// </summary>
/// <typeparam name="TEvent">Event type</typeparam>
/// <param name="eventData">Related data for the event</param>
/// <returns>The task to handle async operation</returns>
Task TriggerAsync<TEvent>(TEvent eventData)
where TEvent : class;
/// <summary>
/// Triggers an event asynchronously.
/// </summary>
/// <param name="eventType">Event type</param>
/// <param name="eventData">Related data for the event</param>
/// <returns>The task to handle async operation</returns>
Task TriggerAsync(Type eventType, object eventData);
}
}

25
framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/IEventPublisher.cs

@ -0,0 +1,25 @@
using System;
using System.Threading.Tasks;
namespace Volo.Abp.EventBus
{
public interface IEventPublisher
{
/// <summary>
/// Triggers an event asynchronously.
/// </summary>
/// <typeparam name="TEvent">Event type</typeparam>
/// <param name="eventData">Related data for the event</param>
/// <returns>The task to handle async operation</returns>
Task PublishAsync<TEvent>(TEvent eventData)
where TEvent : class;
/// <summary>
/// Triggers an event asynchronously.
/// </summary>
/// <param name="eventType">Event type</param>
/// <param name="eventData">Related data for the event</param>
/// <returns>The task to handle async operation</returns>
Task PublishAsync(Type eventType, object eventData);
}
}

111
framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/IEventSubscriber.cs

@ -0,0 +1,111 @@
using System;
using System.Threading.Tasks;
namespace Volo.Abp.EventBus
{
public interface IEventSubscriber
{
/// <summary>
/// Registers to an event.
/// Given action is called for all event occurrences.
/// </summary>
/// <param name="action">Action to handle events</param>
/// <typeparam name="TEvent">Event type</typeparam>
IDisposable Subscribe<TEvent>(Func<TEvent, Task> action)
where TEvent : class;
/// <summary>
/// Registers to an event.
/// Same (given) instance of the handler is used for all event occurrences.
/// </summary>
/// <typeparam name="TEvent">Event type</typeparam>
/// <param name="handler">Object to handle the event</param>
IDisposable Subscribe<TEvent>(IEventHandler<TEvent> handler)
where TEvent : class;
/// <summary>
/// Registers to an event.
/// A new instance of <see cref="THandler"/> object is created for every event occurrence.
/// </summary>
/// <typeparam name="TEvent">Event type</typeparam>
/// <typeparam name="THandler">Type of the event handler</typeparam>
IDisposable Subscribe<TEvent, THandler>()
where TEvent : class
where THandler : IEventHandler, new();
/// <summary>
/// Registers to an event.
/// Same (given) instance of the handler is used for all event occurrences.
/// </summary>
/// <param name="eventType">Event type</param>
/// <param name="handler">Object to handle the event</param>
IDisposable Subscribe(Type eventType, IEventHandler handler);
/// <summary>
/// Registers to an event.
/// Given factory is used to create/release handlers
/// </summary>
/// <typeparam name="TEvent">Event type</typeparam>
/// <param name="factory">A factory to create/release handlers</param>
IDisposable Subscribe<TEvent>(IEventHandlerFactory factory)
where TEvent : class;
/// <summary>
/// Registers to an event.
/// </summary>
/// <param name="eventType">Event type</param>
/// <param name="factory">A factory to create/release handlers</param>
IDisposable Subscribe(Type eventType, IEventHandlerFactory factory);
/// <summary>
/// Unregisters from an event.
/// </summary>
/// <typeparam name="TEvent">Event type</typeparam>
/// <param name="action"></param>
void Unsubscribe<TEvent>(Func<TEvent, Task> action)
where TEvent : class;
/// <summary>
/// Unregisters from an event.
/// </summary>
/// <typeparam name="TEvent">Event type</typeparam>
/// <param name="handler">Handler object that is registered before</param>
void Unsubscribe<TEvent>(IEventHandler<TEvent> handler)
where TEvent : class;
/// <summary>
/// Unregisters from an event.
/// </summary>
/// <param name="eventType">Event type</param>
/// <param name="handler">Handler object that is registered before</param>
void Unsubscribe(Type eventType, IEventHandler handler);
/// <summary>
/// Unregisters from an event.
/// </summary>
/// <typeparam name="TEvent">Event type</typeparam>
/// <param name="factory">Factory object that is registered before</param>
void Unsubscribe<TEvent>(IEventHandlerFactory factory)
where TEvent : class;
/// <summary>
/// Unregisters from an event.
/// </summary>
/// <param name="eventType">Event type</param>
/// <param name="factory">Factory object that is registered before</param>
void Unsubscribe(Type eventType, IEventHandlerFactory factory);
/// <summary>
/// Unregisters all event handlers of given event type.
/// </summary>
/// <typeparam name="TEvent">Event type</typeparam>
void UnsubscribeAll<TEvent>()
where TEvent : class;
/// <summary>
/// Unregisters all event handlers of given event type.
/// </summary>
/// <param name="eventType">Event type</param>
void UnsubscribeAll(Type eventType);
}
}

10
framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Local/ILocalEventBus.cs

@ -0,0 +1,10 @@
namespace Volo.Abp.EventBus.Local
{
/// <summary>
/// Defines interface of the event bus.
/// </summary>
public interface ILocalEventBus : IEventBus
{
}
}

156
framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/EventBus.cs → framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Local/LocalEventBus.cs

@ -1,3 +1,6 @@
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Abstractions;
using Microsoft.Extensions.Options;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
@ -6,47 +9,46 @@ using System.Reflection;
using System.Runtime.CompilerServices;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Abstractions;
using Microsoft.Extensions.Options;
using Volo.Abp.Collections;
using Volo.Abp.DependencyInjection;
using Volo.Abp.EventBus.Distributed;
using Volo.Abp.Reflection;
using Volo.Abp.Threading;
namespace Volo.Abp.EventBus
namespace Volo.Abp.EventBus.Local
{
/// <summary>
/// Implements EventBus as Singleton pattern.
/// </summary>
public class EventBus : IEventBus, ISingletonDependency
[ExposeServices(typeof(ILocalEventBus), typeof(LocalEventBus))]
public class LocalEventBus : ILocalEventBus, ISingletonDependency
{
/// <summary>
/// Reference to the Logger.
/// </summary>
public ILogger<EventBus> Logger { get; set; }
public ILogger<LocalEventBus> Logger { get; set; }
protected EventBusOptions Options { get; }
/// <summary>
/// All registered handler factories.
/// Key: Type of the event
/// Value: List of handler factories
/// </summary>
protected ConcurrentDictionary<Type, List<IEventHandlerFactory>> HandlerFactories { get; }
protected EventBusOptions Options { get; }
protected IServiceProvider ServiceProvider { get; }
public EventBus(
IOptions<EventBusOptions> options,
public LocalEventBus(
IOptions<EventBusOptions> options,
IServiceProvider serviceProvider)
{
ServiceProvider = serviceProvider;
Options = options.Value;
Logger = NullLogger<EventBus>.Instance;
HandlerFactories = new ConcurrentDictionary<Type, List<IEventHandlerFactory>>();
Logger = NullLogger<LocalEventBus>.Instance;
RegisterHandlersInOptions(serviceProvider);
HandlerFactories = new ConcurrentDictionary<Type, List<IEventHandlerFactory>>();
Subscribe(Options.Handlers);
}
protected virtual void RegisterHandlersInOptions(IServiceProvider serviceProvider)
public virtual void Subscribe(ITypeList<IEventHandler> handlers)
{
foreach (var handler in Options.Handlers)
foreach (var handler in handlers)
{
var interfaces = handler.GetInterfaces();
foreach (var @interface in interfaces)
@ -59,46 +61,46 @@ namespace Volo.Abp.EventBus
var genericArgs = @interface.GetGenericArguments();
if (genericArgs.Length == 1)
{
Register(genericArgs[0], new IocEventHandlerFactory(serviceProvider, handler));
Subscribe(genericArgs[0], new IocEventHandlerFactory(ServiceProvider, handler));
}
}
}
}
/// <inheritdoc/>
public IDisposable Register<TEvent>(Func<TEvent, Task> action) where TEvent : class
public IDisposable Subscribe<TEvent>(Func<TEvent, Task> action) where TEvent : class
{
return Register(typeof(TEvent), new ActionEventHandler<TEvent>(action));
return Subscribe(typeof(TEvent), new ActionEventHandler<TEvent>(action));
}
/// <inheritdoc/>
public IDisposable Register<TEvent>(IEventHandler<TEvent> handler) where TEvent : class
public IDisposable Subscribe<TEvent>(IEventHandler<TEvent> handler) where TEvent : class
{
return Register(typeof(TEvent), handler);
return Subscribe(typeof(TEvent), handler);
}
/// <inheritdoc/>
public IDisposable Register<TEvent, THandler>()
public IDisposable Subscribe<TEvent, THandler>()
where TEvent : class
where THandler : IEventHandler, new()
{
return Register(typeof(TEvent), new TransientEventHandlerFactory<THandler>());
return Subscribe(typeof(TEvent), new TransientEventHandlerFactory<THandler>());
}
/// <inheritdoc/>
public IDisposable Register(Type eventType, IEventHandler handler)
public IDisposable Subscribe(Type eventType, IEventHandler handler)
{
return Register(eventType, new SingleInstanceHandlerFactory(handler));
return Subscribe(eventType, new SingleInstanceHandlerFactory(handler));
}
/// <inheritdoc/>
public IDisposable Register<TEvent>(IEventHandlerFactory factory) where TEvent : class
public IDisposable Subscribe<TEvent>(IEventHandlerFactory factory) where TEvent : class
{
return Register(typeof(TEvent), factory);
return Subscribe(typeof(TEvent), factory);
}
/// <inheritdoc/>
public IDisposable Register(Type eventType, IEventHandlerFactory factory)
public IDisposable Subscribe(Type eventType, IEventHandlerFactory factory)
{
GetOrCreateHandlerFactories(eventType)
.Locking(factories => factories.Add(factory));
@ -107,7 +109,7 @@ namespace Volo.Abp.EventBus
}
/// <inheritdoc/>
public void Unregister<TEvent>(Func<TEvent, Task> action) where TEvent : class
public void Unsubscribe<TEvent>(Func<TEvent, Task> action) where TEvent : class
{
Check.NotNull(action, nameof(action));
@ -135,13 +137,13 @@ namespace Volo.Abp.EventBus
}
/// <inheritdoc/>
public void Unregister<TEvent>(IEventHandler<TEvent> handler) where TEvent : class
public void Unsubscribe<TEvent>(IEventHandler<TEvent> handler) where TEvent : class
{
Unregister(typeof(TEvent), handler);
Unsubscribe(typeof(TEvent), handler);
}
/// <inheritdoc/>
public void Unregister(Type eventType, IEventHandler handler)
public void Unsubscribe(Type eventType, IEventHandler handler)
{
GetOrCreateHandlerFactories(eventType)
.Locking(factories =>
@ -150,43 +152,45 @@ namespace Volo.Abp.EventBus
factory =>
factory is SingleInstanceHandlerFactory &&
(factory as SingleInstanceHandlerFactory).HandlerInstance == handler
);
);
});
}
/// <inheritdoc/>
public void Unregister<TEvent>(IEventHandlerFactory factory) where TEvent : class
public void Unsubscribe<TEvent>(IEventHandlerFactory factory) where TEvent : class
{
Unregister(typeof(TEvent), factory);
Unsubscribe(typeof(TEvent), factory);
}
/// <inheritdoc/>
public void Unregister(Type eventType, IEventHandlerFactory factory)
public void Unsubscribe(Type eventType, IEventHandlerFactory factory)
{
GetOrCreateHandlerFactories(eventType).Locking(factories => factories.Remove(factory));
}
/// <inheritdoc/>
public void UnregisterAll<TEvent>() where TEvent : class
public void UnsubscribeAll<TEvent>() where TEvent : class
{
UnregisterAll(typeof(TEvent));
UnsubscribeAll(typeof(TEvent));
}
/// <inheritdoc/>
public void UnregisterAll(Type eventType)
public void UnsubscribeAll(Type eventType)
{
GetOrCreateHandlerFactories(eventType).Locking(factories => factories.Clear());
}
/// <inheritdoc/>
public Task TriggerAsync<TEvent>(TEvent eventData) where TEvent : class
public Task PublishAsync<TEvent>(TEvent eventData) where TEvent : class
{
return TriggerAsync(typeof(TEvent), eventData);
return PublishAsync(typeof(TEvent), eventData);
}
/// <inheritdoc/>
public async Task TriggerAsync(Type eventType, object eventData)
public async Task PublishAsync(Type eventType, object eventData)
{
//TODO: Aggregate all exceptions (including the recursive call)!
var exceptions = new List<Exception>();
await new SynchronizationContextRemover();
@ -199,7 +203,7 @@ namespace Volo.Abp.EventBus
}
}
//Implements generic argument inheritance. See classWithInheritableGenericArgument
//Implements generic argument inheritance. See IEventDataWithInheritableGenericArgument
if (eventType.GetTypeInfo().IsGenericType &&
eventType.GetGenericArguments().Length == 1 &&
typeof(IEventDataWithInheritableGenericArgument).IsAssignableFrom(eventType))
@ -211,7 +215,7 @@ namespace Volo.Abp.EventBus
var baseEventType = eventType.GetGenericTypeDefinition().MakeGenericType(baseArg);
var constructorArgs = ((IEventDataWithInheritableGenericArgument)eventData).GetConstructorArgs();
var baseEventData = Activator.CreateInstance(baseEventType, constructorArgs);
await TriggerAsync(baseEventType, baseEventData);
await PublishAsync(baseEventType, baseEventData);
}
}
@ -232,14 +236,38 @@ namespace Volo.Abp.EventBus
{
try
{
var asyncHandlerType = typeof(IEventHandler<>).MakeGenericType(eventType);
var method = asyncHandlerType.GetMethod(
"HandleEventAsync",
new[] { eventType }
);
var handlerType = eventHandlerWrapper.EventHandler.GetType();
await (Task)method.Invoke(eventHandlerWrapper.EventHandler, new[] { eventData });
if (ReflectionHelper.IsAssignableToGenericType(
handlerType,
typeof(IEventHandler<>)))
{
var method = typeof(IEventHandler<>) //TODO: to a static field
.MakeGenericType(eventType)
.GetMethod(
nameof(IEventHandler<object>.HandleEventAsync),
new[] {eventType}
);
await (Task)method.Invoke(eventHandlerWrapper.EventHandler, new[] { eventData });
}
else if (ReflectionHelper.IsAssignableToGenericType(
handlerType,
typeof(IDistributedEventHandler<>)))
{
var method = typeof(IDistributedEventHandler<>) //TODO: to a static field
.MakeGenericType(eventType)
.GetMethod(
nameof(IDistributedEventHandler<object>.HandleEventAsync),
new[] {eventType}
);
await (Task)method.Invoke(eventHandlerWrapper.EventHandler, new[] { eventData });
}
else
{
throw new AbpException("The object instance is not an event handler. Object type: " + handlerType.AssemblyQualifiedName);
}
}
catch (TargetInvocationException ex)
{
@ -252,7 +280,7 @@ namespace Volo.Abp.EventBus
}
}
private IEnumerable<EventTypeWithEventHandlerFactories> GetHandlerFactories(Type eventType)
public virtual IEnumerable<EventTypeWithEventHandlerFactories> GetHandlerFactories(Type eventType)
{
var handlerFactoryList = new List<EventTypeWithEventHandlerFactories>();
@ -264,16 +292,21 @@ namespace Volo.Abp.EventBus
return handlerFactoryList.ToArray();
}
private static bool ShouldTriggerEventForHandler(Type eventType, Type handlerType)
private List<IEventHandlerFactory> GetOrCreateHandlerFactories(Type eventType)
{
return HandlerFactories.GetOrAdd(eventType, (type) => new List<IEventHandlerFactory>());
}
private static bool ShouldTriggerEventForHandler(Type targetEventType, Type handlerEventType)
{
//Should trigger same type
if (handlerType == eventType)
if (handlerEventType == targetEventType)
{
return true;
}
//Should trigger for inherited types
if (handlerType.IsAssignableFrom(eventType))
if (handlerEventType.IsAssignableFrom(targetEventType))
{
return true;
}
@ -281,12 +314,7 @@ namespace Volo.Abp.EventBus
return false;
}
private List<IEventHandlerFactory> GetOrCreateHandlerFactories(Type eventType)
{
return HandlerFactories.GetOrAdd(eventType, (type) => new List<IEventHandlerFactory>());
}
private class EventTypeWithEventHandlerFactories
public class EventTypeWithEventHandlerFactories
{
public Type EventType { get; }

90
framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/NullEventBus.cs

@ -1,90 +0,0 @@
using System;
using System.Threading.Tasks;
namespace Volo.Abp.EventBus
{
public sealed class NullEventBus : IEventBus
{
public static NullEventBus Instance { get; } = new NullEventBus();
private NullEventBus()
{
}
public IDisposable Register<TEvent>(Func<TEvent, Task> action) where TEvent : class
{
return NullDisposable.Instance;
}
public IDisposable Register<TEvent>(IEventHandler<TEvent> handler) where TEvent : class
{
return NullDisposable.Instance;
}
public IDisposable Register<TEvent, THandler>() where TEvent : class where THandler : IEventHandler, new()
{
return NullDisposable.Instance;
}
public IDisposable Register(Type eventType, IEventHandler handler)
{
return NullDisposable.Instance;
}
public IDisposable Register<TEvent>(IEventHandlerFactory factory) where TEvent : class
{
return NullDisposable.Instance;
}
public IDisposable Register(Type eventType, IEventHandlerFactory factory)
{
return NullDisposable.Instance;
}
public void Unregister<TEvent>(Func<TEvent, Task> action) where TEvent : class
{
}
public void Unregister<TEvent>(IEventHandler<TEvent> handler) where TEvent : class
{
}
public void Unregister(Type eventType, IEventHandler handler)
{
}
public void Unregister<TEvent>(IEventHandlerFactory factory) where TEvent : class
{
}
public void Unregister(Type eventType, IEventHandlerFactory factory)
{
}
public void UnregisterAll<TEvent>() where TEvent : class
{
}
public void UnregisterAll(Type eventType)
{
}
public Task TriggerAsync<TEvent>(TEvent eventData) where TEvent : class
{
return Task.CompletedTask;
}
public Task TriggerAsync(Type eventType, object eventData)
{
return Task.CompletedTask;
}
}
}

91
framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/NullLocalEventBus.cs

@ -0,0 +1,91 @@
using System;
using System.Threading.Tasks;
using Volo.Abp.EventBus.Local;
namespace Volo.Abp.EventBus
{
public sealed class NullLocalEventBus : ILocalEventBus
{
public static NullLocalEventBus Instance { get; } = new NullLocalEventBus();
private NullLocalEventBus()
{
}
public IDisposable Subscribe<TEvent>(Func<TEvent, Task> action) where TEvent : class
{
return NullDisposable.Instance;
}
public IDisposable Subscribe<TEvent>(IEventHandler<TEvent> handler) where TEvent : class
{
return NullDisposable.Instance;
}
public IDisposable Subscribe<TEvent, THandler>() where TEvent : class where THandler : IEventHandler, new()
{
return NullDisposable.Instance;
}
public IDisposable Subscribe(Type eventType, IEventHandler handler)
{
return NullDisposable.Instance;
}
public IDisposable Subscribe<TEvent>(IEventHandlerFactory factory) where TEvent : class
{
return NullDisposable.Instance;
}
public IDisposable Subscribe(Type eventType, IEventHandlerFactory factory)
{
return NullDisposable.Instance;
}
public void Unsubscribe<TEvent>(Func<TEvent, Task> action) where TEvent : class
{
}
public void Unsubscribe<TEvent>(IEventHandler<TEvent> handler) where TEvent : class
{
}
public void Unsubscribe(Type eventType, IEventHandler handler)
{
}
public void Unsubscribe<TEvent>(IEventHandlerFactory factory) where TEvent : class
{
}
public void Unsubscribe(Type eventType, IEventHandlerFactory factory)
{
}
public void UnsubscribeAll<TEvent>() where TEvent : class
{
}
public void UnsubscribeAll(Type eventType)
{
}
public Task PublishAsync<TEvent>(TEvent eventData) where TEvent : class
{
return Task.CompletedTask;
}
public Task PublishAsync(Type eventType, object eventData)
{
return Task.CompletedTask;
}
}
}

7
framework/src/Volo.Abp.MongoDB/Volo/Abp/Domain/Repositories/MongoDB/MongoDbRepository.cs

@ -10,6 +10,7 @@ using Volo.Abp.Auditing;
using Volo.Abp.Domain.Entities;
using Volo.Abp.Domain.Entities.Events;
using Volo.Abp.EventBus;
using Volo.Abp.EventBus.Local;
using Volo.Abp.Guids;
using Volo.Abp.MongoDB;
using Volo.Abp.MultiTenancy;
@ -31,7 +32,7 @@ namespace Volo.Abp.Domain.Repositories.MongoDB
protected IMongoDbContextProvider<TMongoDbContext> DbContextProvider { get; }
public IEventBus EventBus { get; set; }
public ILocalEventBus LocalEventBus { get; set; }
public IEntityChangeEventHelper EntityChangeEventHelper { get; set; }
@ -43,7 +44,7 @@ namespace Volo.Abp.Domain.Repositories.MongoDB
{
DbContextProvider = dbContextProvider;
EventBus = NullEventBus.Instance;
LocalEventBus = NullLocalEventBus.Instance;
EntityChangeEventHelper = NullEntityChangeEventHelper.Instance;
}
@ -313,7 +314,7 @@ namespace Volo.Abp.Domain.Repositories.MongoDB
foreach (var entityEvent in entityEvents)
{
await EventBus.TriggerAsync(entityEvent.GetType(), entityEvent);
await LocalEventBus.PublishAsync(entityEvent.GetType(), entityEvent);
}
generatesDomainEventsEntity.ClearDomainEvents();

17
framework/test/Volo.Abp.EventBus.Tests/Volo/Abp/EventBus/Distributed/LocalDistributedEventBusTestBase.cs

@ -0,0 +1,17 @@
namespace Volo.Abp.EventBus.Distributed
{
public abstract class LocalDistributedEventBusTestBase : AbpIntegratedTest<EventBusTestModule>
{
protected LocalDistributedEventBus LocalEventBus;
protected LocalDistributedEventBusTestBase()
{
LocalEventBus = GetRequiredService<LocalDistributedEventBus>();
}
protected override void SetAbpApplicationCreationOptions(AbpApplicationCreationOptions options)
{
options.UseAutofac();
}
}
}

21
framework/test/Volo.Abp.EventBus.Tests/Volo/Abp/EventBus/Distributed/LocalDistributedEventBus_Test.cs

@ -0,0 +1,21 @@
using System.Threading.Tasks;
using Xunit;
namespace Volo.Abp.EventBus.Distributed
{
public class LocalDistributedEventBus_Test : LocalDistributedEventBusTestBase
{
[Fact]
public async Task Should_Call_Handler_AndDispose()
{
LocalEventBus.Subscribe<MySimpleEventData, MySimpleDistributedTransientEventHandler>();
await LocalEventBus.PublishAsync(new MySimpleEventData(1));
await LocalEventBus.PublishAsync(new MySimpleEventData(2));
await LocalEventBus.PublishAsync(new MySimpleEventData(3));
Assert.Equal(3, MySimpleDistributedTransientEventHandler.HandleCount);
Assert.Equal(3, MySimpleDistributedTransientEventHandler.DisposeCount);
}
}
}

23
framework/test/Volo.Abp.EventBus.Tests/Volo/Abp/EventBus/Distributed/MySimpleDistributedTransientEventHandler.cs

@ -0,0 +1,23 @@
using System;
using System.Threading.Tasks;
namespace Volo.Abp.EventBus.Distributed
{
public class MySimpleDistributedTransientEventHandler : IDistributedEventHandler<MySimpleEventData>, IDisposable
{
public static int HandleCount { get; set; }
public static int DisposeCount { get; set; }
public Task HandleEventAsync(MySimpleEventData eventData)
{
++HandleCount;
return Task.CompletedTask;
}
public void Dispose()
{
++DisposeCount;
}
}
}

48
framework/test/Volo.Abp.EventBus.Tests/Volo/Abp/EventBus/InheritanceTest.cs

@ -1,48 +0,0 @@
using System.Threading.Tasks;
using Xunit;
namespace Volo.Abp.EventBus
{
public class InheritanceTest : EventBusTestBase
{
[Fact]
public async Task Should_Handle_Events_For_Derived_Classes()
{
var totalData = 0;
EventBus.Register<MySimpleEventData>(
eventData =>
{
totalData += eventData.Value;
return Task.CompletedTask;
});
await EventBus.TriggerAsync(new MySimpleEventData(1)); //Should handle directly registered class
await EventBus.TriggerAsync(new MySimpleEventData(2)); //Should handle directly registered class
await EventBus.TriggerAsync(new MyDerivedEventData(3)); //Should handle derived class too
await EventBus.TriggerAsync(new MyDerivedEventData(4)); //Should handle derived class too
Assert.Equal(10, totalData);
}
[Fact]
public async Task Should_Not_Handle_Events_For_Base_Classes()
{
var totalData = 0;
EventBus.Register<MyDerivedEventData>(
eventData =>
{
totalData += eventData.Value;
return Task.CompletedTask;
});
await EventBus.TriggerAsync(new MySimpleEventData(1)); //Should not handle
await EventBus.TriggerAsync(new MySimpleEventData(2)); //Should not handle
await EventBus.TriggerAsync(new MyDerivedEventData(3)); //Should handle
await EventBus.TriggerAsync(new MyDerivedEventData(4)); //Should handle
Assert.Equal(7, totalData);
}
}
}

54
framework/test/Volo.Abp.EventBus.Tests/Volo/Abp/EventBus/ActionBasedEventHandlerTest.cs → framework/test/Volo.Abp.EventBus.Tests/Volo/Abp/EventBus/Local/ActionBasedEventHandlerTest.cs

@ -3,7 +3,7 @@ using System.Threading;
using System.Threading.Tasks;
using Xunit;
namespace Volo.Abp.EventBus
namespace Volo.Abp.EventBus.Local
{
public class ActionBasedEventHandlerTest : EventBusTestBase
{
@ -12,17 +12,17 @@ namespace Volo.Abp.EventBus
{
var totalData = 0;
EventBus.Register<MySimpleEventData>(
LocalEventBus.Subscribe<MySimpleEventData>(
eventData =>
{
totalData += eventData.Value;
return Task.CompletedTask;
});
await EventBus.TriggerAsync(new MySimpleEventData(1));
await EventBus.TriggerAsync(new MySimpleEventData(2));
await EventBus.TriggerAsync(new MySimpleEventData(3));
await EventBus.TriggerAsync(new MySimpleEventData(4));
await LocalEventBus.PublishAsync(new MySimpleEventData(1));
await LocalEventBus.PublishAsync(new MySimpleEventData(2));
await LocalEventBus.PublishAsync(new MySimpleEventData(3));
await LocalEventBus.PublishAsync(new MySimpleEventData(4));
Assert.Equal(10, totalData);
}
@ -32,17 +32,17 @@ namespace Volo.Abp.EventBus
{
var totalData = 0;
EventBus.Register<MySimpleEventData>(
LocalEventBus.Subscribe<MySimpleEventData>(
eventData =>
{
totalData += eventData.Value;
return Task.CompletedTask;
});
await EventBus.TriggerAsync(typeof(MySimpleEventData), new MySimpleEventData(1));
await EventBus.TriggerAsync(typeof(MySimpleEventData), new MySimpleEventData(2));
await EventBus.TriggerAsync(typeof(MySimpleEventData), new MySimpleEventData(3));
await EventBus.TriggerAsync(typeof(MySimpleEventData), new MySimpleEventData(4));
await LocalEventBus.PublishAsync(typeof(MySimpleEventData), new MySimpleEventData(1));
await LocalEventBus.PublishAsync(typeof(MySimpleEventData), new MySimpleEventData(2));
await LocalEventBus.PublishAsync(typeof(MySimpleEventData), new MySimpleEventData(3));
await LocalEventBus.PublishAsync(typeof(MySimpleEventData), new MySimpleEventData(4));
Assert.Equal(10, totalData);
}
@ -52,20 +52,20 @@ namespace Volo.Abp.EventBus
{
var totalData = 0;
var registerDisposer = EventBus.Register<MySimpleEventData>(
var registerDisposer = LocalEventBus.Subscribe<MySimpleEventData>(
eventData =>
{
totalData += eventData.Value;
return Task.CompletedTask;
});
await EventBus.TriggerAsync(new MySimpleEventData(1));
await EventBus.TriggerAsync(new MySimpleEventData(2));
await EventBus.TriggerAsync(new MySimpleEventData(3));
await LocalEventBus.PublishAsync(new MySimpleEventData(1));
await LocalEventBus.PublishAsync(new MySimpleEventData(2));
await LocalEventBus.PublishAsync(new MySimpleEventData(3));
registerDisposer.Dispose();
await EventBus.TriggerAsync(new MySimpleEventData(4));
await LocalEventBus.PublishAsync(new MySimpleEventData(4));
Assert.Equal(6, totalData);
}
@ -82,15 +82,15 @@ namespace Volo.Abp.EventBus
return Task.CompletedTask;
});
EventBus.Register(action);
LocalEventBus.Subscribe(action);
await EventBus.TriggerAsync(new MySimpleEventData(1));
await EventBus.TriggerAsync(new MySimpleEventData(2));
await EventBus.TriggerAsync(new MySimpleEventData(3));
await LocalEventBus.PublishAsync(new MySimpleEventData(1));
await LocalEventBus.PublishAsync(new MySimpleEventData(2));
await LocalEventBus.PublishAsync(new MySimpleEventData(3));
EventBus.Unregister(action);
LocalEventBus.Unsubscribe(action);
await EventBus.TriggerAsync(new MySimpleEventData(4));
await LocalEventBus.PublishAsync(new MySimpleEventData(4));
Assert.Equal(6, totalData);
}
@ -100,7 +100,7 @@ namespace Volo.Abp.EventBus
{
int totalData = 0;
EventBus.Register<MySimpleEventData>(
LocalEventBus.Subscribe<MySimpleEventData>(
async eventData =>
{
await Task.Delay(20);
@ -108,10 +108,10 @@ namespace Volo.Abp.EventBus
await Task.Delay(20);
});
await EventBus.TriggerAsync(new MySimpleEventData(1));
await EventBus.TriggerAsync(new MySimpleEventData(2));
await EventBus.TriggerAsync(new MySimpleEventData(3));
await EventBus.TriggerAsync(new MySimpleEventData(4));
await LocalEventBus.PublishAsync(new MySimpleEventData(1));
await LocalEventBus.PublishAsync(new MySimpleEventData(2));
await LocalEventBus.PublishAsync(new MySimpleEventData(3));
await LocalEventBus.PublishAsync(new MySimpleEventData(4));
Assert.Equal(10, totalData);
}

6
framework/test/Volo.Abp.EventBus.Tests/Volo/Abp/EventBus/EventBusTestBase.cs → framework/test/Volo.Abp.EventBus.Tests/Volo/Abp/EventBus/Local/EventBusTestBase.cs

@ -1,12 +1,12 @@
namespace Volo.Abp.EventBus
namespace Volo.Abp.EventBus.Local
{
public abstract class EventBusTestBase : AbpIntegratedTest<EventBusTestModule>
{
protected IEventBus EventBus;
protected ILocalEventBus LocalEventBus;
protected EventBusTestBase()
{
EventBus = GetRequiredService<IEventBus>();
LocalEventBus = GetRequiredService<ILocalEventBus>();
}
protected override void SetAbpApplicationCreationOptions(AbpApplicationCreationOptions options)

10
framework/test/Volo.Abp.EventBus.Tests/Volo/Abp/EventBus/EventBus_DI_Services_Test.cs → framework/test/Volo.Abp.EventBus.Tests/Volo/Abp/EventBus/Local/EventBus_DI_Services_Test.cs

@ -2,17 +2,17 @@
using Shouldly;
using Xunit;
namespace Volo.Abp.EventBus
namespace Volo.Abp.EventBus.Local
{
public class EventBus_DI_Services_Test : EventBusTestBase
{
[Fact]
public async Task Should_Automatically_Register_EventHandlers_From_Services()
{
await EventBus.TriggerAsync(new MySimpleEventData(1));
await EventBus.TriggerAsync(new MySimpleEventData(2));
await EventBus.TriggerAsync(new MySimpleEventData(3));
await EventBus.TriggerAsync(new MySimpleEventData(4));
await LocalEventBus.PublishAsync(new MySimpleEventData(1));
await LocalEventBus.PublishAsync(new MySimpleEventData(2));
await LocalEventBus.PublishAsync(new MySimpleEventData(3));
await LocalEventBus.PublishAsync(new MySimpleEventData(4));
GetRequiredService<MySimpleEventDataHandler>().TotalData.ShouldBe(10);
}

12
framework/test/Volo.Abp.EventBus.Tests/Volo/Abp/EventBus/EventBus_Exception_Test.cs → framework/test/Volo.Abp.EventBus.Tests/Volo/Abp/EventBus/Local/EventBus_Exception_Test.cs

@ -3,18 +3,18 @@ using System.Threading.Tasks;
using Shouldly;
using Xunit;
namespace Volo.Abp.EventBus
namespace Volo.Abp.EventBus.Local
{
public class EventBus_Exception_Test : EventBusTestBase
{
[Fact]
public async Task Should_Throw_Single_Exception_If_Only_One_Of_Handlers_Fails()
{
EventBus.Register<MySimpleEventData>(eventData => throw new Exception("This exception is intentionally thrown!"));
LocalEventBus.Subscribe<MySimpleEventData>(eventData => throw new Exception("This exception is intentionally thrown!"));
var appException = await Assert.ThrowsAsync<Exception>(async () =>
{
await EventBus.TriggerAsync(new MySimpleEventData(1));
await LocalEventBus.PublishAsync(new MySimpleEventData(1));
});
appException.Message.ShouldBe("This exception is intentionally thrown!");
@ -23,15 +23,15 @@ namespace Volo.Abp.EventBus
[Fact]
public async Task Should_Throw_Aggregate_Exception_If_More_Than_One_Of_Handlers_Fail()
{
EventBus.Register<MySimpleEventData>(
LocalEventBus.Subscribe<MySimpleEventData>(
eventData => throw new Exception("This exception is intentionally thrown #1!"));
EventBus.Register<MySimpleEventData>(
LocalEventBus.Subscribe<MySimpleEventData>(
eventData => throw new Exception("This exception is intentionally thrown #2!"));
var aggrException = await Assert.ThrowsAsync<AggregateException>(async () =>
{
await EventBus.TriggerAsync(new MySimpleEventData(1));
await LocalEventBus.PublishAsync(new MySimpleEventData(1));
});
aggrException.InnerExceptions.Count.ShouldBe(2);

8
framework/test/Volo.Abp.EventBus.Tests/Volo/Abp/EventBus/EventBus_MultipleHandle_Test.cs → framework/test/Volo.Abp.EventBus.Tests/Volo/Abp/EventBus/Local/EventBus_MultipleHandle_Test.cs

@ -4,7 +4,7 @@ using Volo.Abp.Domain.Entities;
using Volo.Abp.Domain.Entities.Events;
using Xunit;
namespace Volo.Abp.EventBus
namespace Volo.Abp.EventBus.Local
{
public class EventBus_EntityEvents_Test : EventBusTestBase
{
@ -13,10 +13,10 @@ namespace Volo.Abp.EventBus
{
var handler = new MyEventHandler();
EventBus.Register<EntityChangedEventData<MyEntity>>(handler);
EventBus.Register<EntityCreatedEventData<MyEntity>>(handler);
LocalEventBus.Subscribe<EntityChangedEventData<MyEntity>>(handler);
LocalEventBus.Subscribe<EntityCreatedEventData<MyEntity>>(handler);
await EventBus.TriggerAsync(new EntityCreatedEventData<MyEntity>(new MyEntity()));
await LocalEventBus.PublishAsync(new EntityCreatedEventData<MyEntity>(new MyEntity()));
handler.EntityCreatedEventCount.ShouldBe(1);
handler.EntityChangedEventCount.ShouldBe(1);

10
framework/test/Volo.Abp.EventBus.Tests/Volo/Abp/EventBus/GenericInheritanceTest.cs → framework/test/Volo.Abp.EventBus.Tests/Volo/Abp/EventBus/Local/GenericInheritanceTest.cs

@ -4,7 +4,7 @@ using Volo.Abp.Domain.Entities;
using Volo.Abp.Domain.Entities.Events;
using Xunit;
namespace Volo.Abp.EventBus
namespace Volo.Abp.EventBus.Local
{
public class GenericInheritanceTest : EventBusTestBase
{
@ -13,7 +13,7 @@ namespace Volo.Abp.EventBus
{
var triggeredEvent = false;
EventBus.Register<EntityChangedEventData<Person>>(
LocalEventBus.Subscribe<EntityChangedEventData<Person>>(
eventData =>
{
eventData.Entity.Id.ShouldBe(42);
@ -21,7 +21,7 @@ namespace Volo.Abp.EventBus
return Task.CompletedTask;
});
await EventBus.TriggerAsync(new EntityUpdatedEventData<Person>(new Person { Id = 42 }));
await LocalEventBus.PublishAsync(new EntityUpdatedEventData<Person>(new Person { Id = 42 }));
triggeredEvent.ShouldBe(true);
}
@ -31,7 +31,7 @@ namespace Volo.Abp.EventBus
{
var triggeredEvent = false;
EventBus.Register<EntityChangedEventData<Person>>(
LocalEventBus.Subscribe<EntityChangedEventData<Person>>(
eventData =>
{
eventData.Entity.Id.ShouldBe(42);
@ -39,7 +39,7 @@ namespace Volo.Abp.EventBus
return Task.CompletedTask;
});
await EventBus.TriggerAsync(new EntityChangedEventData<Student>(new Student { Id = 42 }));
await LocalEventBus.PublishAsync(new EntityChangedEventData<Student>(new Student { Id = 42 }));
triggeredEvent.ShouldBe(true);
}

48
framework/test/Volo.Abp.EventBus.Tests/Volo/Abp/EventBus/Local/InheritanceTest.cs

@ -0,0 +1,48 @@
using System.Threading.Tasks;
using Xunit;
namespace Volo.Abp.EventBus.Local
{
public class InheritanceTest : EventBusTestBase
{
[Fact]
public async Task Should_Handle_Events_For_Derived_Classes()
{
var totalData = 0;
LocalEventBus.Subscribe<MySimpleEventData>(
eventData =>
{
totalData += eventData.Value;
return Task.CompletedTask;
});
await LocalEventBus.PublishAsync(new MySimpleEventData(1)); //Should handle directly registered class
await LocalEventBus.PublishAsync(new MySimpleEventData(2)); //Should handle directly registered class
await LocalEventBus.PublishAsync(new MyDerivedEventData(3)); //Should handle derived class too
await LocalEventBus.PublishAsync(new MyDerivedEventData(4)); //Should handle derived class too
Assert.Equal(10, totalData);
}
[Fact]
public async Task Should_Not_Handle_Events_For_Base_Classes()
{
var totalData = 0;
LocalEventBus.Subscribe<MyDerivedEventData>(
eventData =>
{
totalData += eventData.Value;
return Task.CompletedTask;
});
await LocalEventBus.PublishAsync(new MySimpleEventData(1)); //Should not handle
await LocalEventBus.PublishAsync(new MySimpleEventData(2)); //Should not handle
await LocalEventBus.PublishAsync(new MyDerivedEventData(3)); //Should handle
await LocalEventBus.PublishAsync(new MyDerivedEventData(4)); //Should handle
Assert.Equal(7, totalData);
}
}
}

2
framework/test/Volo.Abp.EventBus.Tests/Volo/Abp/EventBus/MySimpleEventDataHandler.cs → framework/test/Volo.Abp.EventBus.Tests/Volo/Abp/EventBus/Local/MySimpleEventDataHandler.cs

@ -1,7 +1,7 @@
using System.Threading.Tasks;
using Volo.Abp.DependencyInjection;
namespace Volo.Abp.EventBus
namespace Volo.Abp.EventBus.Local
{
public class MySimpleEventDataHandler : IEventHandler<MySimpleEventData>, ISingletonDependency
{

2
framework/test/Volo.Abp.EventBus.Tests/Volo/Abp/EventBus/MySimpleTransientEventHandler.cs → framework/test/Volo.Abp.EventBus.Tests/Volo/Abp/EventBus/Local/MySimpleTransientEventHandler.cs

@ -1,7 +1,7 @@
using System;
using System.Threading.Tasks;
namespace Volo.Abp.EventBus
namespace Volo.Abp.EventBus.Local
{
public class MySimpleTransientEventHandler : IEventHandler<MySimpleEventData>, IDisposable
{

10
framework/test/Volo.Abp.EventBus.Tests/Volo/Abp/EventBus/TransientDisposableEventHandlerTest.cs → framework/test/Volo.Abp.EventBus.Tests/Volo/Abp/EventBus/Local/TransientDisposableEventHandlerTest.cs

@ -1,18 +1,18 @@
using System.Threading.Tasks;
using Xunit;
namespace Volo.Abp.EventBus
namespace Volo.Abp.EventBus.Local
{
public class TransientDisposableEventHandlerTest : EventBusTestBase
{
[Fact]
public async Task Should_Call_Handler_AndDispose()
{
EventBus.Register<MySimpleEventData, MySimpleTransientEventHandler>();
LocalEventBus.Subscribe<MySimpleEventData, MySimpleTransientEventHandler>();
await EventBus.TriggerAsync(new MySimpleEventData(1));
await EventBus.TriggerAsync(new MySimpleEventData(2));
await EventBus.TriggerAsync(new MySimpleEventData(3));
await LocalEventBus.PublishAsync(new MySimpleEventData(1));
await LocalEventBus.PublishAsync(new MySimpleEventData(2));
await LocalEventBus.PublishAsync(new MySimpleEventData(3));
Assert.Equal(3, MySimpleTransientEventHandler.HandleCount);
Assert.Equal(3, MySimpleTransientEventHandler.DisposeCount);

7
framework/test/Volo.Abp.TestApp/Volo/Abp/TestApp/Testing/DomainEvents_Tests.cs

@ -4,6 +4,7 @@ using System.Threading.Tasks;
using Shouldly;
using Volo.Abp.Domain.Repositories;
using Volo.Abp.EventBus;
using Volo.Abp.EventBus.Local;
using Volo.Abp.Modularity;
using Volo.Abp.TestApp.Domain;
using Xunit;
@ -14,12 +15,12 @@ namespace Volo.Abp.TestApp.Testing
where TStartupModule : IAbpModule
{
protected readonly IRepository<Person, Guid> PersonRepository;
protected readonly IEventBus EventBus;
protected readonly ILocalEventBus LocalEventBus;
protected DomainEvents_Tests()
{
PersonRepository = GetRequiredService<IRepository<Person, Guid>>();
EventBus = GetRequiredService<IEventBus>();
LocalEventBus = GetRequiredService<ILocalEventBus>();
}
[Fact]
@ -29,7 +30,7 @@ namespace Volo.Abp.TestApp.Testing
var isTriggered = false;
EventBus.Register<PersonNameChangedEvent>(data =>
LocalEventBus.Subscribe<PersonNameChangedEvent>(data =>
{
data.OldName.ShouldBe("Douglas");
data.Person.Name.ShouldBe("Douglas-Changed");

13
framework/test/Volo.Abp.TestApp/Volo/Abp/TestApp/Testing/EntityChangeEvents_Tests.cs

@ -4,6 +4,7 @@ using Shouldly;
using Volo.Abp.Domain.Entities.Events;
using Volo.Abp.Domain.Repositories;
using Volo.Abp.EventBus;
using Volo.Abp.EventBus.Local;
using Volo.Abp.Modularity;
using Volo.Abp.TestApp.Domain;
using Volo.Abp.Uow;
@ -15,12 +16,12 @@ namespace Volo.Abp.TestApp.Testing
where TStartupModule : IAbpModule
{
protected IRepository<Person, Guid> PersonRepository { get; }
protected IEventBus EventBus { get; }
protected ILocalEventBus LocalEventBus { get; }
protected EntityChangeEvents_Tests()
{
PersonRepository = GetRequiredService<IRepository<Person, Guid>>();
EventBus = GetRequiredService<IEventBus>();
LocalEventBus = GetRequiredService<ILocalEventBus>();
}
[Fact]
@ -35,7 +36,7 @@ namespace Volo.Abp.TestApp.Testing
using (var uow = GetRequiredService<IUnitOfWorkManager>().Begin())
{
EventBus.Register<EntityCreatingEventData<Person>>(data =>
LocalEventBus.Subscribe<EntityCreatingEventData<Person>>(data =>
{
creatingEventTriggered.ShouldBeFalse();
createdEventTriggered.ShouldBeFalse();
@ -54,7 +55,7 @@ namespace Volo.Abp.TestApp.Testing
return Task.CompletedTask;
});
EventBus.Register<EntityCreatedEventData<Person>>(data =>
LocalEventBus.Subscribe<EntityCreatedEventData<Person>>(data =>
{
creatingEventTriggered.ShouldBeTrue();
createdEventTriggered.ShouldBeFalse();
@ -69,7 +70,7 @@ namespace Volo.Abp.TestApp.Testing
return Task.CompletedTask;
});
EventBus.Register<EntityUpdatingEventData<Person>>(data =>
LocalEventBus.Subscribe<EntityUpdatingEventData<Person>>(data =>
{
creatingEventTriggered.ShouldBeTrue();
createdEventTriggered.ShouldBeFalse();
@ -84,7 +85,7 @@ namespace Volo.Abp.TestApp.Testing
return Task.CompletedTask;
});
EventBus.Register<EntityUpdatedEventData<Person>>(data =>
LocalEventBus.Subscribe<EntityUpdatedEventData<Person>>(data =>
{
creatingEventTriggered.ShouldBeTrue();
createdEventTriggered.ShouldBeTrue();

Loading…
Cancel
Save