diff --git a/src/Volo.Abp.EventBus/Volo/Abp/EventBus/AbpEventBusModule.cs b/src/Volo.Abp.EventBus/Volo/Abp/EventBus/AbpEventBusModule.cs index 2eabf6db80..75e38d586c 100644 --- a/src/Volo.Abp.EventBus/Volo/Abp/EventBus/AbpEventBusModule.cs +++ b/src/Volo.Abp.EventBus/Volo/Abp/EventBus/AbpEventBusModule.cs @@ -1,13 +1,43 @@ -using Microsoft.Extensions.DependencyInjection; +using System; +using System.Collections.Generic; +using System.Linq; +using Microsoft.Extensions.DependencyInjection; +using Volo.Abp.EventBus.Handlers; using Volo.Abp.Modularity; namespace Volo.Abp.EventBus { public class AbpEventBusModule : AbpModule { + public override void PreConfigureServices(IServiceCollection services) + { + AddEventHandlers(services); + } + public override void ConfigureServices(IServiceCollection services) { services.AddAssemblyOf(); } + + private static void AddEventHandlers(IServiceCollection services) + { + var handlers = new List(); + + services.OnRegistred(context => + { + if (context.ImplementationType.GetInterfaces().Any(i => typeof(IEventHandler).IsAssignableFrom(i))) + { + handlers.Add(context.ImplementationType); + } + }); + + services.Configure(options => + { + foreach (var handler in handlers) + { + options.Handlers.AddIfNotContains(handler); + } + }); + } } } diff --git a/src/Volo.Abp.EventBus/Volo/Abp/EventBus/EventBus.cs b/src/Volo.Abp.EventBus/Volo/Abp/EventBus/EventBus.cs index 8472fddd1d..fad8006126 100644 --- a/src/Volo.Abp.EventBus/Volo/Abp/EventBus/EventBus.cs +++ b/src/Volo.Abp.EventBus/Volo/Abp/EventBus/EventBus.cs @@ -8,6 +8,7 @@ using System.Threading; using System.Threading.Tasks; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging.Abstractions; +using Microsoft.Extensions.Options; using Volo.Abp.DependencyInjection; using Volo.Abp.EventBus.Factories; using Volo.Abp.EventBus.Factories.Internals; @@ -22,11 +23,6 @@ namespace Volo.Abp.EventBus /// public class EventBus : IEventBus, ISingletonDependency { - /// - /// Gets the default instance. - /// - public static EventBus Instance { get; } = new EventBus(); - /// /// Reference to the Logger. /// @@ -37,16 +33,38 @@ namespace Volo.Abp.EventBus /// Key: Type of the event /// Value: List of handler factories /// - private readonly ConcurrentDictionary> _handlerFactories; + protected ConcurrentDictionary> HandlerFactories { get; } - /// - /// Creates a new instance. - /// Instead of creating a new instace, you can use to use Global . - /// - public EventBus() + protected EventBusOptions Options { get; } + + public EventBus(IOptions options, IServiceProvider serviceProvider) { - _handlerFactories = new ConcurrentDictionary>(); + Options = options.Value; Logger = NullLogger.Instance; + HandlerFactories = new ConcurrentDictionary>(); + + RegisterHandlersInOptions(serviceProvider); + } + + protected virtual void RegisterHandlersInOptions(IServiceProvider serviceProvider) + { + foreach (var handler in Options.Handlers) + { + var interfaces = handler.GetInterfaces(); + foreach (var @interface in interfaces) + { + if (!typeof(IEventHandler).GetTypeInfo().IsAssignableFrom(@interface)) + { + continue; + } + + var genericArgs = @interface.GetGenericArguments(); + if (genericArgs.Length == 1) + { + Register(genericArgs[0], new IocHandlerFactory(serviceProvider, handler)); + } + } + } } /// @@ -416,7 +434,7 @@ namespace Volo.Abp.EventBus { var handlerFactoryList = new List(); - foreach (var handlerFactory in _handlerFactories.Where(hf => ShouldTriggerEventForHandler(eventType, hf.Key))) + foreach (var handlerFactory in HandlerFactories.Where(hf => ShouldTriggerEventForHandler(eventType, hf.Key))) { handlerFactoryList.Add(new EventTypeWithEventHandlerFactories(handlerFactory.Key, handlerFactory.Value)); } @@ -443,7 +461,7 @@ namespace Volo.Abp.EventBus private List GetOrCreateHandlerFactories(Type eventType) { - return _handlerFactories.GetOrAdd(eventType, (type) => new List()); + return HandlerFactories.GetOrAdd(eventType, (type) => new List()); } private class EventTypeWithEventHandlerFactories diff --git a/src/Volo.Abp.EventBus/Volo/Abp/EventBus/EventBusOptions.cs b/src/Volo.Abp.EventBus/Volo/Abp/EventBus/EventBusOptions.cs new file mode 100644 index 0000000000..2363c58984 --- /dev/null +++ b/src/Volo.Abp.EventBus/Volo/Abp/EventBus/EventBusOptions.cs @@ -0,0 +1,15 @@ +using Volo.Abp.Collections; +using Volo.Abp.EventBus.Handlers; + +namespace Volo.Abp.EventBus +{ + public class EventBusOptions + { + public ITypeList Handlers { get; } + + public EventBusOptions() + { + Handlers = new TypeList(); + } + } +} \ No newline at end of file diff --git a/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Factories/IocHandlerFactory.cs b/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Factories/IocHandlerFactory.cs index 36b220bb2f..a9bff4803b 100644 --- a/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Factories/IocHandlerFactory.cs +++ b/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Factories/IocHandlerFactory.cs @@ -10,18 +10,10 @@ namespace Volo.Abp.EventBus.Factories /// public class IocHandlerFactory : IEventHandlerFactory { - /// - /// Type of the handler. - /// public Type HandlerType { get; } private readonly IServiceProvider _iocResolver; - /// - /// Creates a new instance of class. - /// - /// - /// Type of the handler public IocHandlerFactory(IServiceProvider iocResolver, Type handlerType) { _iocResolver = iocResolver; @@ -42,10 +34,6 @@ namespace Volo.Abp.EventBus.Factories return HandlerType; } - /// - /// Releases handler object using Ioc container. - /// - /// Handler to be released public void ReleaseHandler(IEventHandler handler) { //TODO: Scope!!! diff --git a/test/Volo.Abp.EventBus.Tests/Volo.Abp.EventBus.Tests.csproj b/test/Volo.Abp.EventBus.Tests/Volo.Abp.EventBus.Tests.csproj index b57069aaaf..87d8359990 100644 --- a/test/Volo.Abp.EventBus.Tests/Volo.Abp.EventBus.Tests.csproj +++ b/test/Volo.Abp.EventBus.Tests/Volo.Abp.EventBus.Tests.csproj @@ -13,6 +13,7 @@ + diff --git a/test/Volo.Abp.EventBus.Tests/Volo/Abp/EventBus/EventBusTestBase.cs b/test/Volo.Abp.EventBus.Tests/Volo/Abp/EventBus/EventBusTestBase.cs index 3206bd1ac1..5f198a17b6 100644 --- a/test/Volo.Abp.EventBus.Tests/Volo/Abp/EventBus/EventBusTestBase.cs +++ b/test/Volo.Abp.EventBus.Tests/Volo/Abp/EventBus/EventBusTestBase.cs @@ -10,5 +10,10 @@ namespace Volo.Abp.EventBus { EventBus = GetRequiredService(); } + + protected override void SetAbpApplicationCreationOptions(AbpApplicationCreationOptions options) + { + options.UseAutofac(); + } } } \ No newline at end of file diff --git a/test/Volo.Abp.EventBus.Tests/Volo/Abp/EventBus/EventBus_DI_Services_Test.cs b/test/Volo.Abp.EventBus.Tests/Volo/Abp/EventBus/EventBus_DI_Services_Test.cs new file mode 100644 index 0000000000..21af339052 --- /dev/null +++ b/test/Volo.Abp.EventBus.Tests/Volo/Abp/EventBus/EventBus_DI_Services_Test.cs @@ -0,0 +1,21 @@ +using System.Threading.Tasks; +using Shouldly; +using Xunit; + +namespace Volo.Abp.EventBus +{ + public class EventBus_DI_Services_Test : EventBusTestBase + { + [Fact] + public async Task Should_Automatically_Register_EventHandlers_From_Services() + { + EventBus.Trigger(new MySimpleEventData(1)); + await EventBus.TriggerAsync(new MySimpleEventData(2)); + EventBus.Trigger(new MySimpleEventData(3)); + await EventBus.TriggerAsync(new MySimpleEventData(4)); + + GetRequiredService().TotalData.ShouldBe(10); + GetRequiredService().TotalData.ShouldBe(10); + } + } +} diff --git a/test/Volo.Abp.EventBus.Tests/Volo/Abp/EventBus/MySimpleAsyncEventDataHandler.cs b/test/Volo.Abp.EventBus.Tests/Volo/Abp/EventBus/MySimpleAsyncEventDataHandler.cs new file mode 100644 index 0000000000..73af47a7bd --- /dev/null +++ b/test/Volo.Abp.EventBus.Tests/Volo/Abp/EventBus/MySimpleAsyncEventDataHandler.cs @@ -0,0 +1,17 @@ +using System.Threading.Tasks; +using Volo.Abp.DependencyInjection; +using Volo.Abp.EventBus.Handlers; + +namespace Volo.Abp.EventBus +{ + public class MySimpleAsyncEventDataHandler : IAsyncEventHandler, ISingletonDependency + { + public int TotalData { get; private set; } + + public Task HandleEventAsync(MySimpleEventData eventData) + { + TotalData += eventData.Value; + return Task.CompletedTask; + } + } +} \ No newline at end of file diff --git a/test/Volo.Abp.EventBus.Tests/Volo/Abp/EventBus/MySimpleEventDataHandler.cs b/test/Volo.Abp.EventBus.Tests/Volo/Abp/EventBus/MySimpleEventDataHandler.cs new file mode 100644 index 0000000000..e4f6cab484 --- /dev/null +++ b/test/Volo.Abp.EventBus.Tests/Volo/Abp/EventBus/MySimpleEventDataHandler.cs @@ -0,0 +1,15 @@ +using Volo.Abp.DependencyInjection; +using Volo.Abp.EventBus.Handlers; + +namespace Volo.Abp.EventBus +{ + public class MySimpleEventDataHandler : IEventHandler, ISingletonDependency + { + public int TotalData { get; private set; } + + public void HandleEvent(MySimpleEventData eventData) + { + TotalData += eventData.Value; + } + } +} \ No newline at end of file