Auto register event handlers registered to IOC.

pull/216/head
Halil İbrahim Kalkan 8 years ago
parent 389f9e7996
commit 479f0a08e9

@ -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<AbpEventBusModule>();
}
private static void AddEventHandlers(IServiceCollection services)
{
var handlers = new List<Type>();
services.OnRegistred(context =>
{
if (context.ImplementationType.GetInterfaces().Any(i => typeof(IEventHandler).IsAssignableFrom(i)))
{
handlers.Add(context.ImplementationType);
}
});
services.Configure<EventBusOptions>(options =>
{
foreach (var handler in handlers)
{
options.Handlers.AddIfNotContains(handler);
}
});
}
}
}

@ -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
/// </summary>
public class EventBus : IEventBus, ISingletonDependency
{
/// <summary>
/// Gets the default <see cref="EventBus"/> instance.
/// </summary>
public static EventBus Instance { get; } = new EventBus();
/// <summary>
/// Reference to the Logger.
/// </summary>
@ -37,16 +33,38 @@ namespace Volo.Abp.EventBus
/// Key: Type of the event
/// Value: List of handler factories
/// </summary>
private readonly ConcurrentDictionary<Type, List<IEventHandlerFactory>> _handlerFactories;
protected ConcurrentDictionary<Type, List<IEventHandlerFactory>> HandlerFactories { get; }
/// <summary>
/// Creates a new <see cref="EventBus"/> instance.
/// Instead of creating a new instace, you can use <see cref="Instance"/> to use Global <see cref="EventBus"/>.
/// </summary>
public EventBus()
protected EventBusOptions Options { get; }
public EventBus(IOptions<EventBusOptions> options, IServiceProvider serviceProvider)
{
_handlerFactories = new ConcurrentDictionary<Type, List<IEventHandlerFactory>>();
Options = options.Value;
Logger = NullLogger<EventBus>.Instance;
HandlerFactories = new ConcurrentDictionary<Type, List<IEventHandlerFactory>>();
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));
}
}
}
}
/// <inheritdoc/>
@ -416,7 +434,7 @@ namespace Volo.Abp.EventBus
{
var handlerFactoryList = new List<EventTypeWithEventHandlerFactories>();
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<IEventHandlerFactory> GetOrCreateHandlerFactories(Type eventType)
{
return _handlerFactories.GetOrAdd(eventType, (type) => new List<IEventHandlerFactory>());
return HandlerFactories.GetOrAdd(eventType, (type) => new List<IEventHandlerFactory>());
}
private class EventTypeWithEventHandlerFactories

@ -0,0 +1,15 @@
using Volo.Abp.Collections;
using Volo.Abp.EventBus.Handlers;
namespace Volo.Abp.EventBus
{
public class EventBusOptions
{
public ITypeList<IEventHandler> Handlers { get; }
public EventBusOptions()
{
Handlers = new TypeList<IEventHandler>();
}
}
}

@ -10,18 +10,10 @@ namespace Volo.Abp.EventBus.Factories
/// </summary>
public class IocHandlerFactory : IEventHandlerFactory
{
/// <summary>
/// Type of the handler.
/// </summary>
public Type HandlerType { get; }
private readonly IServiceProvider _iocResolver;
/// <summary>
/// Creates a new instance of <see cref="IocHandlerFactory"/> class.
/// </summary>
/// <param name="iocResolver"></param>
/// <param name="handlerType">Type of the handler</param>
public IocHandlerFactory(IServiceProvider iocResolver, Type handlerType)
{
_iocResolver = iocResolver;
@ -42,10 +34,6 @@ namespace Volo.Abp.EventBus.Factories
return HandlerType;
}
/// <summary>
/// Releases handler object using Ioc container.
/// </summary>
/// <param name="handler">Handler to be released</param>
public void ReleaseHandler(IEventHandler handler)
{
//TODO: Scope!!!

@ -13,6 +13,7 @@
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\..\src\Volo.Abp.Autofac\Volo.Abp.Autofac.csproj" />
<ProjectReference Include="..\AbpTestBase\AbpTestBase.csproj" />
<ProjectReference Include="..\..\src\Volo.Abp.Ddd\Volo.Abp.Ddd.csproj" />
<ProjectReference Include="..\..\src\Volo.Abp.EventBus\Volo.Abp.EventBus.csproj" />

@ -10,5 +10,10 @@ namespace Volo.Abp.EventBus
{
EventBus = GetRequiredService<IEventBus>();
}
protected override void SetAbpApplicationCreationOptions(AbpApplicationCreationOptions options)
{
options.UseAutofac();
}
}
}

@ -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<MySimpleEventDataHandler>().TotalData.ShouldBe(10);
GetRequiredService<MySimpleAsyncEventDataHandler>().TotalData.ShouldBe(10);
}
}
}

@ -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<MySimpleEventData>, ISingletonDependency
{
public int TotalData { get; private set; }
public Task HandleEventAsync(MySimpleEventData eventData)
{
TotalData += eventData.Value;
return Task.CompletedTask;
}
}
}

@ -0,0 +1,15 @@
using Volo.Abp.DependencyInjection;
using Volo.Abp.EventBus.Handlers;
namespace Volo.Abp.EventBus
{
public class MySimpleEventDataHandler : IEventHandler<MySimpleEventData>, ISingletonDependency
{
public int TotalData { get; private set; }
public void HandleEvent(MySimpleEventData eventData)
{
TotalData += eventData.Value;
}
}
}
Loading…
Cancel
Save