Browse Source

Created Volo.Abp.EventBus package.

pull/216/head
Halil İbrahim Kalkan 9 years ago
parent
commit
68a3f9ccb5
  1. 7
      Volo.Abp.sln
  2. 20
      src/Volo.Abp.EventBus/Volo.Abp.EventBus.csproj
  3. 13
      src/Volo.Abp.EventBus/Volo/Abp/EventBus/AbpEventBusModule.cs
  4. 495
      src/Volo.Abp.EventBus/Volo/Abp/EventBus/EventBus.cs
  5. 29
      src/Volo.Abp.EventBus/Volo/Abp/EventBus/Factories/IEventHandlerFactory.cs
  6. 26
      src/Volo.Abp.EventBus/Volo/Abp/EventBus/Factories/Internals/FactoryUnregistrar.cs
  7. 45
      src/Volo.Abp.EventBus/Volo/Abp/EventBus/Factories/Internals/SingleInstanceHandlerFactory.cs
  8. 42
      src/Volo.Abp.EventBus/Volo/Abp/EventBus/Factories/Internals/TransientEventHandlerFactory.cs
  9. 55
      src/Volo.Abp.EventBus/Volo/Abp/EventBus/Factories/IocHandlerFactory.cs
  10. 17
      src/Volo.Abp.EventBus/Volo/Abp/EventBus/Handlers/IAsyncEventHandlerOfTEventData.cs
  11. 11
      src/Volo.Abp.EventBus/Volo/Abp/EventBus/Handlers/IEventHandler.cs
  12. 15
      src/Volo.Abp.EventBus/Volo/Abp/EventBus/Handlers/IEventHandlerOfTEventData.cs
  13. 37
      src/Volo.Abp.EventBus/Volo/Abp/EventBus/Handlers/Internals/ActionEventHandler.cs
  14. 38
      src/Volo.Abp.EventBus/Volo/Abp/EventBus/Handlers/Internals/AsyncActionEventHandler.cs
  15. 7
      src/Volo.Abp.EventBus/Volo/Abp/EventBus/IDistributedEventBus.cs
  16. 194
      src/Volo.Abp.EventBus/Volo/Abp/EventBus/IEventBus.cs
  17. 20
      src/Volo.Abp.EventBus/Volo/Abp/EventBus/IEventDataWithInheritableGenericArgument.cs
  18. 122
      src/Volo.Abp.EventBus/Volo/Abp/EventBus/NullEventBus.cs
  19. 11
      src/Volo.Abp.Permissions.Domain/Volo/Abp/Permissions/PermissionStore.cs

7
Volo.Abp.sln

@ -276,6 +276,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Abp.Permissions.Applic
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.Caching", "src\Volo.Abp.Caching\Volo.Abp.Caching.csproj", "{A5B650AB-A67F-4A4C-9F81-7B5471CA1331}" Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.Caching", "src\Volo.Abp.Caching\Volo.Abp.Caching.csproj", "{A5B650AB-A67F-4A4C-9F81-7B5471CA1331}"
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.EventBus", "src\Volo.Abp.EventBus\Volo.Abp.EventBus.csproj", "{D9455AE7-2E0C-4647-9880-F5831BCEE3D8}"
EndProject
Global Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU Debug|Any CPU = Debug|Any CPU
@ -722,6 +724,10 @@ Global
{A5B650AB-A67F-4A4C-9F81-7B5471CA1331}.Debug|Any CPU.Build.0 = Debug|Any CPU {A5B650AB-A67F-4A4C-9F81-7B5471CA1331}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A5B650AB-A67F-4A4C-9F81-7B5471CA1331}.Release|Any CPU.ActiveCfg = Release|Any CPU {A5B650AB-A67F-4A4C-9F81-7B5471CA1331}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A5B650AB-A67F-4A4C-9F81-7B5471CA1331}.Release|Any CPU.Build.0 = Release|Any CPU {A5B650AB-A67F-4A4C-9F81-7B5471CA1331}.Release|Any CPU.Build.0 = Release|Any CPU
{D9455AE7-2E0C-4647-9880-F5831BCEE3D8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{D9455AE7-2E0C-4647-9880-F5831BCEE3D8}.Debug|Any CPU.Build.0 = Debug|Any CPU
{D9455AE7-2E0C-4647-9880-F5831BCEE3D8}.Release|Any CPU.ActiveCfg = Release|Any CPU
{D9455AE7-2E0C-4647-9880-F5831BCEE3D8}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection EndGlobalSection
GlobalSection(SolutionProperties) = preSolution GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE HideSolutionNode = FALSE
@ -856,6 +862,7 @@ Global
{837ABFF5-66EE-486A-8023-8DD3EE7D7D96} = {055F4AC0-46C4-4E99-89CD-0F30D4A97382} {837ABFF5-66EE-486A-8023-8DD3EE7D7D96} = {055F4AC0-46C4-4E99-89CD-0F30D4A97382}
{90197499-CBB6-4C8C-90E6-8718CD755C04} = {055F4AC0-46C4-4E99-89CD-0F30D4A97382} {90197499-CBB6-4C8C-90E6-8718CD755C04} = {055F4AC0-46C4-4E99-89CD-0F30D4A97382}
{A5B650AB-A67F-4A4C-9F81-7B5471CA1331} = {4C753F64-0C93-4D65-96C2-A40893AFC1E8} {A5B650AB-A67F-4A4C-9F81-7B5471CA1331} = {4C753F64-0C93-4D65-96C2-A40893AFC1E8}
{D9455AE7-2E0C-4647-9880-F5831BCEE3D8} = {4C753F64-0C93-4D65-96C2-A40893AFC1E8}
EndGlobalSection EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {BB97ECF4-9A84-433F-A80B-2A3285BDD1D5} SolutionGuid = {BB97ECF4-9A84-433F-A80B-2A3285BDD1D5}

20
src/Volo.Abp.EventBus/Volo.Abp.EventBus.csproj

@ -0,0 +1,20 @@
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="..\..\common.props" />
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<AssemblyName>Volo.Abp.EventBus</AssemblyName>
<PackageId>Volo.Abp.EventBus</PackageId>
<AssetTargetFallback>$(AssetTargetFallback);portable-net45+win8+wp8+wpa81;</AssetTargetFallback>
<GenerateAssemblyConfigurationAttribute>false</GenerateAssemblyConfigurationAttribute>
<GenerateAssemblyCompanyAttribute>false</GenerateAssemblyCompanyAttribute>
<GenerateAssemblyProductAttribute>false</GenerateAssemblyProductAttribute>
<RootNamespace />
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\Volo.Abp.Core\Volo.Abp.Core.csproj" />
</ItemGroup>
</Project>

13
src/Volo.Abp.EventBus/Volo/Abp/EventBus/AbpEventBusModule.cs

@ -0,0 +1,13 @@
using Microsoft.Extensions.DependencyInjection;
using Volo.Abp.Modularity;
namespace Volo.Abp.EventBus
{
public class AbpEventBusModule : AbpModule
{
public override void ConfigureServices(IServiceCollection services)
{
services.AddAssemblyOf<AbpEventBusModule>();
}
}
}

495
src/Volo.Abp.EventBus/Volo/Abp/EventBus/EventBus.cs

@ -0,0 +1,495 @@
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Abstractions;
using Volo.Abp.DependencyInjection;
using Volo.Abp.EventBus.Factories;
using Volo.Abp.EventBus.Factories.Internals;
using Volo.Abp.EventBus.Handlers;
using Volo.Abp.EventBus.Handlers.Internals;
using Volo.Abp.Threading;
namespace Volo.Abp.EventBus
{
/// <summary>
/// Implements EventBus as Singleton pattern.
/// </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>
public ILogger<EventBus> Logger { get; set; }
/// <summary>
/// All registered handler factories.
/// Key: Type of the event
/// Value: List of handler factories
/// </summary>
private readonly ConcurrentDictionary<Type, List<IEventHandlerFactory>> _handlerFactories;
/// <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()
{
_handlerFactories = new ConcurrentDictionary<Type, List<IEventHandlerFactory>>();
Logger = NullLogger<EventBus>.Instance;
}
/// <inheritdoc/>
public IDisposable Register<TEventData>(Action<TEventData> action)
where TEventData : class
{
return Register(typeof(TEventData), new ActionEventHandler<TEventData>(action));
}
/// <inheritdoc/>
public IDisposable AsyncRegister<TEventData>(Func<TEventData, Task> action) where TEventData : class
{
return Register(typeof(TEventData), new AsyncActionEventHandler<TEventData>(action));
}
/// <inheritdoc/>
public IDisposable Register<TEventData>(IEventHandler<TEventData> handler) where TEventData : class
{
return Register(typeof(TEventData), handler);
}
/// <inheritdoc/>
public IDisposable AsyncRegister<TEventData>(IAsyncEventHandler<TEventData> handler) where TEventData : class
{
return Register(typeof(TEventData), handler);
}
/// <inheritdoc/>
public IDisposable Register<TEventData, THandler>()
where TEventData : class
where THandler : IEventHandler, new()
{
return Register(typeof(TEventData), new TransientEventHandlerFactory<THandler>());
}
/// <inheritdoc/>
public IDisposable Register(Type eventType, IEventHandler handler)
{
return Register(eventType, new SingleInstanceHandlerFactory(handler));
}
/// <inheritdoc/>
public IDisposable Register<TEventData>(IEventHandlerFactory factory) where TEventData : class
{
return Register(typeof(TEventData), factory);
}
/// <inheritdoc/>
public IDisposable Register(Type eventType, IEventHandlerFactory factory)
{
GetOrCreateHandlerFactories(eventType)
.Locking(factories => factories.Add(factory));
return new FactoryUnregistrar(this, eventType, factory);
}
/// <inheritdoc/>
public void Unregister<TEventData>(Action<TEventData> action) where TEventData : class
{
Check.NotNull(action, nameof(action));
GetOrCreateHandlerFactories(typeof(TEventData))
.Locking(factories =>
{
factories.RemoveAll(
factory =>
{
var singleInstanceFactory = factory as SingleInstanceHandlerFactory;
if (singleInstanceFactory == null)
{
return false;
}
var actionHandler = singleInstanceFactory.HandlerInstance as ActionEventHandler<TEventData>;
if (actionHandler == null)
{
return false;
}
return actionHandler.Action == action;
});
});
}
/// <inheritdoc/>
public void AsyncUnregister<TEventData>(Func<TEventData, Task> action) where TEventData : class
{
Check.NotNull(action, nameof(action));
GetOrCreateHandlerFactories(typeof(TEventData))
.Locking(factories =>
{
factories.RemoveAll(
factory =>
{
var singleInstanceFactory = factory as SingleInstanceHandlerFactory;
if (singleInstanceFactory == null)
{
return false;
}
var actionHandler = singleInstanceFactory.HandlerInstance as AsyncActionEventHandler<TEventData>;
if (actionHandler == null)
{
return false;
}
return actionHandler.Action == action;
});
});
}
/// <inheritdoc/>
public void Unregister<TEventData>(IEventHandler<TEventData> handler) where TEventData : class
{
Unregister(typeof(TEventData), handler);
}
/// <inheritdoc/>
public void AsyncUnregister<TEventData>(IAsyncEventHandler<TEventData> handler) where TEventData : class
{
Unregister(typeof(TEventData), handler);
}
/// <inheritdoc/>
public void Unregister(Type eventType, IEventHandler handler)
{
GetOrCreateHandlerFactories(eventType)
.Locking(factories =>
{
factories.RemoveAll(
factory =>
factory is SingleInstanceHandlerFactory &&
(factory as SingleInstanceHandlerFactory).HandlerInstance == handler
);
});
}
/// <inheritdoc/>
public void Unregister<TEventData>(IEventHandlerFactory factory) where TEventData : class
{
Unregister(typeof(TEventData), factory);
}
/// <inheritdoc/>
public void Unregister(Type eventType, IEventHandlerFactory factory)
{
GetOrCreateHandlerFactories(eventType).Locking(factories => factories.Remove(factory));
}
/// <inheritdoc/>
public void UnregisterAll<TEventData>() where TEventData : class
{
UnregisterAll(typeof(TEventData));
}
/// <inheritdoc/>
public void UnregisterAll(Type eventType)
{
GetOrCreateHandlerFactories(eventType).Locking(factories => factories.Clear());
}
/// <inheritdoc/>
public void Trigger<TEventData>(TEventData eventData) where TEventData : class
{
Trigger(typeof(TEventData), eventData);
}
/// <inheritdoc/>
public void Trigger(Type eventType, object eventData)
{
var exceptions = new List<Exception>();
foreach (var handlerFactories in GetHandlerFactories(eventType))
{
foreach (var handlerFactory in handlerFactories.EventHandlerFactories)
{
var handlerType = handlerFactory.GetHandlerType();
if (IsAsyncEventHandler(handlerType))
{
AsyncHelper.RunSync(() => TriggerAsyncHandlingException(handlerFactory, handlerFactories.EventType, eventData, exceptions));
}
else if (IsEventHandler(handlerType))
{
TriggerHandlingException(handlerFactory, handlerFactories.EventType, eventData, exceptions);
}
else
{
var message = $"Event handler to register for event type {eventType.Name} does not implement IEventHandler<{eventType.Name}> or IAsyncEventHandler<{eventType.Name}> interface!";
exceptions.Add(new AbpException(message));
}
}
}
//Implements generic argument inheritance. See classWithInheritableGenericArgument
if (eventType.GetTypeInfo().IsGenericType &&
eventType.GetGenericArguments().Length == 1 &&
typeof(IEventDataWithInheritableGenericArgument).IsAssignableFrom(eventType))
{
var genericArg = eventType.GetGenericArguments()[0];
var baseArg = genericArg.GetTypeInfo().BaseType;
if (baseArg != null)
{
var baseEventType = eventType.GetGenericTypeDefinition().MakeGenericType(baseArg);
var constructorArgs = ((IEventDataWithInheritableGenericArgument)eventData).GetConstructorArgs();
var baseEventData = Activator.CreateInstance(baseEventType, constructorArgs);
Trigger(baseEventType, baseEventData);
}
}
if (exceptions.Any())
{
if (exceptions.Count == 1)
{
exceptions[0].ReThrow();
}
throw new AggregateException("More than one error has occurred while triggering the event: " + eventType, exceptions);
}
}
/// <inheritdoc/>
public Task TriggerAsync<TEventData>(TEventData eventData) where TEventData : class
{
return TriggerAsync(typeof(TEventData), eventData);
}
/// <inheritdoc/>
public async Task TriggerAsync(Type eventType, object eventData)
{
var exceptions = new List<Exception>();
await new SynchronizationContextRemover();
foreach (var handlerFactories in GetHandlerFactories(eventType))
{
foreach (var handlerFactory in handlerFactories.EventHandlerFactories)
{
var handlerType = handlerFactory.GetHandlerType();
if (IsAsyncEventHandler(handlerType))
{
await TriggerAsyncHandlingException(handlerFactory, handlerFactories.EventType, eventData, exceptions);
}
else if (IsEventHandler(handlerType))
{
TriggerHandlingException(handlerFactory, handlerFactories.EventType, eventData, exceptions);
}
else
{
var message = $"Event handler to register for event type {eventType.Name} does not implement IEventHandler<{eventType.Name}> or IAsyncEventHandler<{eventType.Name}> interface!";
exceptions.Add(new AbpException(message));
}
}
}
//Implements generic argument inheritance. See classWithInheritableGenericArgument
if (eventType.GetTypeInfo().IsGenericType &&
eventType.GetGenericArguments().Length == 1 &&
typeof(IEventDataWithInheritableGenericArgument).IsAssignableFrom(eventType))
{
var genericArg = eventType.GetGenericArguments()[0];
var baseArg = genericArg.GetTypeInfo().BaseType;
if (baseArg != null)
{
var baseEventType = eventType.GetGenericTypeDefinition().MakeGenericType(baseArg);
var constructorArgs = ((IEventDataWithInheritableGenericArgument)eventData).GetConstructorArgs();
var baseEventData = Activator.CreateInstance(baseEventType, constructorArgs);
await TriggerAsync(baseEventType, baseEventData);
}
}
if (exceptions.Any())
{
if (exceptions.Count == 1)
{
exceptions[0].ReThrow();
}
throw new AggregateException("More than one error has occurred while triggering the event: " + eventType, exceptions);
}
}
private void TriggerHandlingException(IEventHandlerFactory handlerFactory, Type eventType, object eventData, List<Exception> exceptions)
{
var eventHandler = handlerFactory.GetHandler();
try
{
if (eventHandler == null)
{
throw new ArgumentNullException($"Registered event handler for event type {eventType.Name} is null!");
}
var handlerType = typeof(IEventHandler<>).MakeGenericType(eventType);
var method = handlerType.GetMethod(
"HandleEvent",
new[] { eventType }
);
method.Invoke(eventHandler, new[] { eventData });
}
catch (TargetInvocationException ex)
{
exceptions.Add(ex.InnerException);
}
catch (Exception ex)
{
exceptions.Add(ex);
}
finally
{
handlerFactory.ReleaseHandler(eventHandler);
}
}
private async Task TriggerAsyncHandlingException(IEventHandlerFactory asyncHandlerFactory, Type eventType, object eventData, List<Exception> exceptions)
{
var asyncEventHandler = asyncHandlerFactory.GetHandler();
try
{
if (asyncEventHandler == null)
{
throw new ArgumentNullException($"Registered async event handler for event type {eventType.Name} is null!");
}
var asyncHandlerType = typeof(IAsyncEventHandler<>).MakeGenericType(eventType);
var method = asyncHandlerType.GetMethod(
"HandleEventAsync",
new[] { eventType }
);
await (Task)method.Invoke(asyncEventHandler, new[] { eventData });
}
catch (TargetInvocationException ex)
{
exceptions.Add(ex.InnerException);
}
catch (Exception ex)
{
exceptions.Add(ex);
}
finally
{
asyncHandlerFactory.ReleaseHandler(asyncEventHandler);
}
}
private bool IsEventHandler(Type handlerType)
{
return handlerType.GetInterfaces()
.Where(i => i.IsGenericType)
.Any(i => i.GetGenericTypeDefinition() == typeof(IEventHandler<>));
}
private bool IsAsyncEventHandler(Type handlerType)
{
return handlerType.GetInterfaces()
.Where(i => i.IsGenericType)
.Any(i => i.GetGenericTypeDefinition() == typeof(IAsyncEventHandler<>));
}
private IEnumerable<EventTypeWithEventHandlerFactories> GetHandlerFactories(Type eventType)
{
var handlerFactoryList = new List<EventTypeWithEventHandlerFactories>();
foreach (var handlerFactory in _handlerFactories.Where(hf => ShouldTriggerEventForHandler(eventType, hf.Key)))
{
handlerFactoryList.Add(new EventTypeWithEventHandlerFactories(handlerFactory.Key, handlerFactory.Value));
}
return handlerFactoryList.ToArray();
}
private static bool ShouldTriggerEventForHandler(Type eventType, Type handlerType)
{
//Should trigger same type
if (handlerType == eventType)
{
return true;
}
//Should trigger for inherited types
if (handlerType.IsAssignableFrom(eventType))
{
return true;
}
return false;
}
private List<IEventHandlerFactory> GetOrCreateHandlerFactories(Type eventType)
{
return _handlerFactories.GetOrAdd(eventType, (type) => new List<IEventHandlerFactory>());
}
private class EventTypeWithEventHandlerFactories
{
public Type EventType { get; }
public List<IEventHandlerFactory> EventHandlerFactories { get; }
public EventTypeWithEventHandlerFactories(Type eventType, List<IEventHandlerFactory> eventHandlerFactories)
{
EventType = eventType;
EventHandlerFactories = eventHandlerFactories;
}
}
// Reference from
// https://blogs.msdn.microsoft.com/benwilli/2017/02/09/an-alternative-to-configureawaitfalse-everywhere/
private struct SynchronizationContextRemover : INotifyCompletion
{
public bool IsCompleted
{
get { return SynchronizationContext.Current == null; }
}
public void OnCompleted(Action continuation)
{
var prevContext = SynchronizationContext.Current;
try
{
SynchronizationContext.SetSynchronizationContext(null);
continuation();
}
finally
{
SynchronizationContext.SetSynchronizationContext(prevContext);
}
}
public SynchronizationContextRemover GetAwaiter()
{
return this;
}
public void GetResult()
{
}
}
}
}

29
src/Volo.Abp.EventBus/Volo/Abp/EventBus/Factories/IEventHandlerFactory.cs

@ -0,0 +1,29 @@
using System;
using Volo.Abp.EventBus.Handlers;
namespace Volo.Abp.EventBus.Factories
{
/// <summary>
/// Defines an interface for factories those are responsible to create/get and release of event handlers.
/// </summary>
public interface IEventHandlerFactory
{
/// <summary>
/// Gets an event handler.
/// </summary>
/// <returns>The event handler</returns>
IEventHandler GetHandler();
/// <summary>
/// Gets type of the handler (without creating an instance).
/// </summary>
/// <returns></returns>
Type GetHandlerType();
/// <summary>
/// Releases an event handler.
/// </summary>
/// <param name="handler">Handle to be released</param>
void ReleaseHandler(IEventHandler handler);
}
}

26
src/Volo.Abp.EventBus/Volo/Abp/EventBus/Factories/Internals/FactoryUnregistrar.cs

@ -0,0 +1,26 @@
using System;
namespace Volo.Abp.EventBus.Factories.Internals
{
/// <summary>
/// Used to unregister a <see cref="IEventHandlerFactory"/> on <see cref="Dispose"/> method.
/// </summary>
internal class FactoryUnregistrar : IDisposable
{
private readonly IEventBus _eventBus;
private readonly Type _eventType;
private readonly IEventHandlerFactory _factory;
public FactoryUnregistrar(IEventBus eventBus, Type eventType, IEventHandlerFactory factory)
{
_eventBus = eventBus;
_eventType = eventType;
_factory = factory;
}
public void Dispose()
{
_eventBus.Unregister(_eventType, _factory);
}
}
}

45
src/Volo.Abp.EventBus/Volo/Abp/EventBus/Factories/Internals/SingleInstanceHandlerFactory.cs

@ -0,0 +1,45 @@
using System;
using Volo.Abp.DynamicProxy;
using Volo.Abp.EventBus.Handlers;
namespace Volo.Abp.EventBus.Factories.Internals
{
/// <summary>
/// This <see cref="IEventHandlerFactory"/> implementation is used to handle events
/// by a single instance object.
/// </summary>
/// <remarks>
/// This class always gets the same single instance of handler.
/// </remarks>
internal class SingleInstanceHandlerFactory : IEventHandlerFactory
{
/// <summary>
/// The event handler instance.
/// </summary>
public IEventHandler HandlerInstance { get; private set; }
/// <summary>
///
/// </summary>
/// <param name="handler"></param>
public SingleInstanceHandlerFactory(IEventHandler handler)
{
HandlerInstance = handler;
}
public IEventHandler GetHandler()
{
return HandlerInstance;
}
public Type GetHandlerType()
{
return ProxyHelper.UnProxy(HandlerInstance).GetType();
}
public void ReleaseHandler(IEventHandler handler)
{
}
}
}

42
src/Volo.Abp.EventBus/Volo/Abp/EventBus/Factories/Internals/TransientEventHandlerFactory.cs

@ -0,0 +1,42 @@
using System;
using Volo.Abp.EventBus.Handlers;
namespace Volo.Abp.EventBus.Factories.Internals
{
/// <summary>
/// This <see cref="IEventHandlerFactory"/> implementation is used to handle events
/// by a transient instance object.
/// </summary>
/// <remarks>
/// This class always creates a new transient instance of handler.
/// </remarks>
internal class TransientEventHandlerFactory<THandler> : IEventHandlerFactory
where THandler : IEventHandler, new()
{
/// <summary>
/// Creates a new instance of the handler object.
/// </summary>
/// <returns>The handler object</returns>
public IEventHandler GetHandler()
{
return new THandler();
}
public Type GetHandlerType()
{
return typeof(THandler);
}
/// <summary>
/// Disposes the handler object if it's <see cref="IDisposable"/>. Does nothing if it's not.
/// </summary>
/// <param name="handler">Handler to be released</param>
public void ReleaseHandler(IEventHandler handler)
{
if (handler is IDisposable)
{
(handler as IDisposable).Dispose();
}
}
}
}

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

@ -0,0 +1,55 @@
using System;
using Microsoft.Extensions.DependencyInjection;
using Volo.Abp.EventBus.Handlers;
namespace Volo.Abp.EventBus.Factories
{
/// <summary>
/// This <see cref="IEventHandlerFactory"/> implementation is used to get/release
/// handlers using Ioc.
/// </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;
HandlerType = handlerType;
}
/// <summary>
/// Resolves handler object from Ioc container.
/// </summary>
/// <returns>Resolved handler object</returns>
public IEventHandler GetHandler()
{
return (IEventHandler)_iocResolver.GetRequiredService(HandlerType);
}
public Type GetHandlerType()
{
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!!!
//_iocResolver.Release(handler);
}
}
}

17
src/Volo.Abp.EventBus/Volo/Abp/EventBus/Handlers/IAsyncEventHandlerOfTEventData.cs

@ -0,0 +1,17 @@
using System.Threading.Tasks;
namespace Volo.Abp.EventBus.Handlers
{
/// <summary>
/// Defines an interface of a class that handles events asynchrounously of type <see cref="IAsyncEventHandler{TEventData}"/>.
/// </summary>
/// <typeparam name="TEventData">Event type to handle</typeparam>
public interface IAsyncEventHandler<in TEventData> : IEventHandler
{
/// <summary>
/// Handler handles the event by implementing this method.
/// </summary>
/// <param name="eventData">Event data</param>
Task HandleEventAsync(TEventData eventData);
}
}

11
src/Volo.Abp.EventBus/Volo/Abp/EventBus/Handlers/IEventHandler.cs

@ -0,0 +1,11 @@
namespace Volo.Abp.EventBus.Handlers
{
/// <summary>
/// Undirect base interface for all event handlers.
/// Implement <see cref="IEventHandler{TEventData}"/> instead of this one.
/// </summary>
public interface IEventHandler
{
}
}

15
src/Volo.Abp.EventBus/Volo/Abp/EventBus/Handlers/IEventHandlerOfTEventData.cs

@ -0,0 +1,15 @@
namespace Volo.Abp.EventBus.Handlers
{
/// <summary>
/// Defines an interface of a class that handles events of type <see cref="IEventHandler{TEventData}"/>.
/// </summary>
/// <typeparam name="TEventData">Event type to handle</typeparam>
public interface IEventHandler<in TEventData> : IEventHandler
{
/// <summary>
/// Handler handles the event by implementing this method.
/// </summary>
/// <param name="eventData">Event data</param>
void HandleEvent(TEventData eventData);
}
}

37
src/Volo.Abp.EventBus/Volo/Abp/EventBus/Handlers/Internals/ActionEventHandler.cs

@ -0,0 +1,37 @@
using System;
using Volo.Abp.DependencyInjection;
namespace Volo.Abp.EventBus.Handlers.Internals
{
/// <summary>
/// This event handler is an adapter to be able to use an action as <see cref="IEventHandler{TEventData}"/> implementation.
/// </summary>
/// <typeparam name="TEventData">Event type</typeparam>
internal class ActionEventHandler<TEventData> :
IEventHandler<TEventData>,
ITransientDependency
{
/// <summary>
/// Action to handle the event.
/// </summary>
public Action<TEventData> Action { get; private set; }
/// <summary>
/// Creates a new instance of <see cref="ActionEventHandler{TEventData}"/>.
/// </summary>
/// <param name="handler">Action to handle the event</param>
public ActionEventHandler(Action<TEventData> handler)
{
Action = handler;
}
/// <summary>
/// Handles the event.
/// </summary>
/// <param name="eventData"></param>
public void HandleEvent(TEventData eventData)
{
Action(eventData);
}
}
}

38
src/Volo.Abp.EventBus/Volo/Abp/EventBus/Handlers/Internals/AsyncActionEventHandler.cs

@ -0,0 +1,38 @@
using System;
using System.Threading.Tasks;
using Volo.Abp.DependencyInjection;
namespace Volo.Abp.EventBus.Handlers.Internals
{
/// <summary>
/// This event handler is an adapter to be able to use an action as <see cref="IAsyncEventHandler{TEventData}"/> implementation.
/// </summary>
/// <typeparam name="TEventData">Event type</typeparam>
internal class AsyncActionEventHandler<TEventData> :
IAsyncEventHandler<TEventData>,
ITransientDependency
{
/// <summary>
/// Function to handle the event.
/// </summary>
public Func<TEventData, Task> Action { get; private set; }
/// <summary>
/// Creates a new instance of <see cref="AsyncActionEventHandler{TEventData}"/>.
/// </summary>
/// <param name="handler">Action to handle the event</param>
public AsyncActionEventHandler(Func<TEventData, Task> handler)
{
Action = handler;
}
/// <summary>
/// Handles the event.
/// </summary>
/// <param name="eventData"></param>
public async Task HandleEventAsync(TEventData eventData)
{
await Action(eventData);
}
}
}

7
src/Volo.Abp.EventBus/Volo/Abp/EventBus/IDistributedEventBus.cs

@ -0,0 +1,7 @@
namespace Volo.Abp.EventBus
{
public interface IDistributedEventBus
{
}
}

194
src/Volo.Abp.EventBus/Volo/Abp/EventBus/IEventBus.cs

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

20
src/Volo.Abp.EventBus/Volo/Abp/EventBus/IEventDataWithInheritableGenericArgument.cs

@ -0,0 +1,20 @@
namespace Volo.Abp.EventBus
{
/// <summary>
/// This interface must be implemented by event data classes that
/// has a single generic argument and this argument will be used by inheritance.
///
/// For example;
/// Assume that Student inherits From Person. When trigger an EntityCreatedEventData{Student},
/// EntityCreatedEventData{Person} is also triggered if EntityCreatedEventData implements
/// this interface.
/// </summary>
public interface IEventDataWithInheritableGenericArgument
{
/// <summary>
/// Gets arguments to create this class since a new instance of this class is created.
/// </summary>
/// <returns>Constructor arguments</returns>
object[] GetConstructorArgs();
}
}

122
src/Volo.Abp.EventBus/Volo/Abp/EventBus/NullEventBus.cs

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

11
src/Volo.Abp.Permissions.Domain/Volo/Abp/Permissions/PermissionStore.cs

@ -9,12 +9,13 @@ using Volo.Abp.Threading;
namespace Volo.Abp.Permissions namespace Volo.Abp.Permissions
{ {
/* TODOS: /* TODO:
* - Wrap distributed cache? * - Cache Invalidation (via entity events - eventbus)
* - Wrap distributed cache
* - Add multi-tenancy * - Add multi-tenancy
* - Add _cancellationTokenProvider support * - Add _cancellationTokenProvider support
* - Add object serialization support * - Add object serialization support
* - Add cache invalidation support..? Maybe it's not cache's job! * - Wrap in-memory cache!
*/ */
public class PermissionStore : AbpServiceBase, IPermissionStore, ITransientDependency public class PermissionStore : AbpServiceBase, IPermissionStore, ITransientDependency
@ -47,11 +48,11 @@ namespace Volo.Abp.Permissions
private string CalculateCacheKey(string name, string providerName, string providerKey) private string CalculateCacheKey(string name, string providerName, string providerKey)
{ {
var key = "P:" + providerName + "_K:" + providerKey + "N:" + name; var key = "P:" + providerName + "#K:" + providerKey + "#N:" + name;
if (_currentTenant.Id.HasValue) if (_currentTenant.Id.HasValue)
{ {
key = "T:" + _currentTenant.Id + "_" + key; key = "T:" + _currentTenant.Id + "#" + key;
} }
return key; return key;

Loading…
Cancel
Save