Browse Source

Auto register event handlers registered to IOC.

pull/216/head
Halil İbrahim Kalkan 9 years ago
parent
commit
479f0a08e9
  1. 32
      src/Volo.Abp.EventBus/Volo/Abp/EventBus/AbpEventBusModule.cs
  2. 46
      src/Volo.Abp.EventBus/Volo/Abp/EventBus/EventBus.cs
  3. 15
      src/Volo.Abp.EventBus/Volo/Abp/EventBus/EventBusOptions.cs
  4. 12
      src/Volo.Abp.EventBus/Volo/Abp/EventBus/Factories/IocHandlerFactory.cs
  5. 1
      test/Volo.Abp.EventBus.Tests/Volo.Abp.EventBus.Tests.csproj
  6. 5
      test/Volo.Abp.EventBus.Tests/Volo/Abp/EventBus/EventBusTestBase.cs
  7. 21
      test/Volo.Abp.EventBus.Tests/Volo/Abp/EventBus/EventBus_DI_Services_Test.cs
  8. 17
      test/Volo.Abp.EventBus.Tests/Volo/Abp/EventBus/MySimpleAsyncEventDataHandler.cs
  9. 15
      test/Volo.Abp.EventBus.Tests/Volo/Abp/EventBus/MySimpleEventDataHandler.cs

32
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<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);
}
});
}
}
}

46
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
/// </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

15
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<IEventHandler> Handlers { get; }
public EventBusOptions()
{
Handlers = new TypeList<IEventHandler>();
}
}
}

12
src/Volo.Abp.EventBus/Volo/Abp/EventBus/Factories/IocHandlerFactory.cs

@ -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!!!

1
test/Volo.Abp.EventBus.Tests/Volo.Abp.EventBus.Tests.csproj

@ -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" />

5
test/Volo.Abp.EventBus.Tests/Volo/Abp/EventBus/EventBusTestBase.cs

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

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

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

15
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<MySimpleEventData>, ISingletonDependency
{
public int TotalData { get; private set; }
public void HandleEvent(MySimpleEventData eventData)
{
TotalData += eventData.Value;
}
}
}
Loading…
Cancel
Save