Browse Source

Refactor.

pull/11232/head
maliming 5 years ago
parent
commit
f0a8362135
No known key found for this signature in database GPG Key ID: 96224957E51C89E
  1. 9
      framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/EventBusBase.cs
  2. 37
      framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/EventHandlerInvoker.cs
  3. 70
      framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/EventHandlerMethodExecutor.cs
  4. 3
      framework/test/Volo.Abp.EventBus.Tests/Volo/Abp/EventBus/EventHandlerInvoker_Tests.cs

9
framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/EventBusBase.cs

@ -214,14 +214,7 @@ public abstract class EventBusBase : IEventBus
using (CurrentTenant.Change(GetEventDataTenantId(eventData))) using (CurrentTenant.Change(GetEventDataTenantId(eventData)))
{ {
if (ReflectionHelper.IsAssignableToGenericType(handlerType, typeof(ILocalEventHandler<>)) || ReflectionHelper.IsAssignableToGenericType(handlerType, typeof(IDistributedEventHandler<>))) await EventHandlerInvoker.InvokeAsync(eventHandlerWrapper.EventHandler, eventData, eventType);
{
await EventHandlerInvoker.InvokeAsync(eventHandlerWrapper.EventHandler, eventData, eventType);
}
else
{
throw new AbpException("The object instance is not an event handler. Object type: " + handlerType.AssemblyQualifiedName);
}
} }
} }
catch (TargetInvocationException ex) catch (TargetInvocationException ex)

37
framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/EventHandlerInvoker.cs

@ -1,35 +1,40 @@
using System; using System;
using System.Collections.Concurrent; using System.Collections.Concurrent;
using System.Linq;
using System.Reflection;
using System.Threading.Tasks; using System.Threading.Tasks;
using Volo.Abp.DependencyInjection; using Volo.Abp.DependencyInjection;
using Volo.Abp.EventBus.Distributed;
namespace Volo.Abp.EventBus; namespace Volo.Abp.EventBus;
public class EventHandlerInvoker : IEventHandlerInvoker, ISingletonDependency public class EventHandlerInvoker : IEventHandlerInvoker, ISingletonDependency
{ {
private const string EventHandlerMethodName = "HandleEventAsync"; private readonly ConcurrentDictionary<string, IEventHandlerMethodExecutor> _cache;
private readonly ConcurrentDictionary<string, EventHandlerMethodExecutor> _executorCache;
public EventHandlerInvoker() public EventHandlerInvoker()
{ {
_executorCache = new ConcurrentDictionary<string, EventHandlerMethodExecutor>(); _cache = new ConcurrentDictionary<string, IEventHandlerMethodExecutor>();
} }
public Task InvokeAsync(IEventHandler eventHandler, object eventData, Type eventType) public async Task InvokeAsync(IEventHandler eventHandler, object eventData, Type eventType)
{ {
var handleType = eventHandler.GetType(); if (typeof(ILocalEventHandler<>).MakeGenericType(eventType).IsInstanceOfType(eventHandler))
var key = $"{handleType.FullName}_{eventType.FullName}"; {
var eventHandlerCall = _cache.GetOrAdd($"{typeof(LocalEventHandlerMethodExecutor<>).FullName}{eventHandler.GetType().FullName}-{eventType.FullName}",
(_) => (IEventHandlerMethodExecutor)Activator.CreateInstance(typeof(LocalEventHandlerMethodExecutor<>).MakeGenericType(eventType)));
await eventHandlerCall.ExecutorAsync(eventHandler, eventData);
}
var executor = _executorCache.GetOrAdd(key, _ => EventHandlerMethodExecutor.Create(GetHandleEventMethodInfo(handleType, eventType), handleType.GetTypeInfo())); if (typeof(IDistributedEventHandler<>).MakeGenericType(eventType).IsInstanceOfType(eventHandler))
{
var eventHandlerCall = _cache.GetOrAdd($"{typeof(DistributedEventHandlerMethodExecutor<>).FullName}{eventHandler.GetType().FullName}-{eventType.FullName}",
(_) => (IEventHandlerMethodExecutor)Activator.CreateInstance(typeof(DistributedEventHandlerMethodExecutor<>).MakeGenericType(eventType)));
await eventHandlerCall.ExecutorAsync(eventHandler, eventData);
}
return executor.ExecuteAsync(eventHandler, new[] { eventData }); if (!typeof(ILocalEventHandler<>).MakeGenericType(eventType).IsInstanceOfType(eventHandler) &&
} !typeof(IDistributedEventHandler<>).MakeGenericType(eventType).IsInstanceOfType(eventHandler))
{
private static MethodInfo GetHandleEventMethodInfo(Type handleType, Type eventType) throw new AbpException("The object instance is not an event handler. Object type: " + eventHandler.GetType().AssemblyQualifiedName);
{ }
var methods = handleType.GetMethods().Where(x => x.Name == EventHandlerMethodName).ToArray();
return methods.Length == 1 ? methods.First() : methods.FirstOrDefault(x => x.GetParameters().Any(param => param.ParameterType == eventType));
} }
} }

70
framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/EventHandlerMethodExecutor.cs

@ -1,66 +1,34 @@
using System; using System;
using System.Collections.Generic;
using System.Linq.Expressions;
using System.Reflection;
using System.Threading.Tasks; using System.Threading.Tasks;
using Volo.Abp.EventBus.Distributed;
namespace Volo.Abp.EventBus; namespace Volo.Abp.EventBus;
public class EventHandlerMethodExecutor public delegate Task EventHandlerMethodExecutorAsync(IEventHandler target, object parameter);
{
private readonly MethodExecutorAsync _executorAsync;
private delegate Task MethodExecutorAsync(IEventHandler target, object[] parameters);
public MethodInfo MethodInfo { get; } public interface IEventHandlerMethodExecutor
{
EventHandlerMethodExecutorAsync ExecutorAsync { get; }
}
public TypeInfo TargetTypeInfo { get; } public class LocalEventHandlerMethodExecutor<TEvent> : IEventHandlerMethodExecutor
where TEvent : class
{
public EventHandlerMethodExecutorAsync ExecutorAsync => (target, parameter) => target.As<ILocalEventHandler<TEvent>>().HandleEventAsync(parameter.As<TEvent>());
private EventHandlerMethodExecutor(MethodInfo methodInfo, TypeInfo targetTypeInfo) public Task ExecuteAsync(IEventHandler target, TEvent parameters)
{ {
if (methodInfo == null) return ExecutorAsync(target, parameters);
{
throw new ArgumentNullException(nameof(methodInfo));
}
MethodInfo = methodInfo;
TargetTypeInfo = targetTypeInfo;
_executorAsync = GetExecutorAsync(methodInfo, targetTypeInfo);
}
private static MethodExecutorAsync GetExecutorAsync(MethodInfo methodInfo, TypeInfo targetTypeInfo)
{
var targetParameter = Expression.Parameter(typeof(IEventHandler), "target");
var parametersParameter = Expression.Parameter(typeof(object[]), "parameters");
var paramInfos = methodInfo.GetParameters();
var parameters = new List<Expression>(paramInfos.Length);
for (var i = 0; i < paramInfos.Length; i++)
{
var paramInfo = paramInfos[i];
var valueObj = Expression.ArrayIndex(parametersParameter, Expression.Constant(i));
var valueCast = Expression.Convert(valueObj, paramInfo.ParameterType);
parameters.Add(valueCast);
}
var instanceCast = Expression.Convert(targetParameter, targetTypeInfo.AsType());
var methodCall = Expression.Call(instanceCast, methodInfo, parameters);
var castMethodCall = Expression.Convert(methodCall, typeof(Task));
var lambda = Expression.Lambda<MethodExecutorAsync>(castMethodCall, targetParameter, parametersParameter);
return lambda.Compile();
} }
}
public static EventHandlerMethodExecutor Create(MethodInfo methodInfo, TypeInfo targetTypeInfo) public class DistributedEventHandlerMethodExecutor<TEvent> : IEventHandlerMethodExecutor
{ where TEvent : class
return new EventHandlerMethodExecutor(methodInfo, targetTypeInfo); {
} public EventHandlerMethodExecutorAsync ExecutorAsync => (target, parameter) => target.As<IDistributedEventHandler<TEvent>>().HandleEventAsync(parameter.As<TEvent>());
public Task ExecuteAsync(IEventHandler target, object[] parameters) public Task ExecuteAsync(IEventHandler target, TEvent parameters)
{ {
return _executorAsync(target, parameters); return ExecutorAsync(target, parameters);
} }
} }

3
framework/test/Volo.Abp.EventBus.Tests/Volo/Abp/EventBus/EventHandlerInvoker_Tests.cs

@ -27,7 +27,7 @@ public class EventHandlerInvoker_Tests : EventBusTestBase
await _eventHandlerInvoker.InvokeAsync(localHandler, eventData, eventData.GetType()); await _eventHandlerInvoker.InvokeAsync(localHandler, eventData, eventData.GetType());
localHandler.MyEventDataCount.ShouldBe(1); localHandler.MyEventDataCount.ShouldBe(2);
localHandler.EntityChangedEventDataCount.ShouldBe(0); localHandler.EntityChangedEventDataCount.ShouldBe(0);
localHandler.EntityChangedEventDataCount.ShouldBe(0); localHandler.EntityChangedEventDataCount.ShouldBe(0);
} }
@ -99,6 +99,7 @@ public class EventHandlerInvoker_Tests : EventBusTestBase
} }
public class MyLocalEventHandler : ILocalEventHandler<MyEventData>, public class MyLocalEventHandler : ILocalEventHandler<MyEventData>,
IDistributedEventHandler<MyEventData>,
IDistributedEventHandler<EntityCreatedEventData<MyEntity>>, IDistributedEventHandler<EntityCreatedEventData<MyEntity>>,
IDistributedEventHandler<EntityChangedEventData<MyEntity>> IDistributedEventHandler<EntityChangedEventData<MyEntity>>
{ {

Loading…
Cancel
Save