diff --git a/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/EventBusBase.cs b/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/EventBusBase.cs index bc307a1777..6e48b27e5f 100644 --- a/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/EventBusBase.cs +++ b/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/EventBusBase.cs @@ -214,14 +214,7 @@ public abstract class EventBusBase : IEventBus using (CurrentTenant.Change(GetEventDataTenantId(eventData))) { - if (ReflectionHelper.IsAssignableToGenericType(handlerType, typeof(ILocalEventHandler<>)) || ReflectionHelper.IsAssignableToGenericType(handlerType, typeof(IDistributedEventHandler<>))) - { - await EventHandlerInvoker.InvokeAsync(eventHandlerWrapper.EventHandler, eventData, eventType); - } - else - { - throw new AbpException("The object instance is not an event handler. Object type: " + handlerType.AssemblyQualifiedName); - } + await EventHandlerInvoker.InvokeAsync(eventHandlerWrapper.EventHandler, eventData, eventType); } } catch (TargetInvocationException ex) diff --git a/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/EventHandlerInvoker.cs b/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/EventHandlerInvoker.cs index 35d1f4e74c..6269500687 100644 --- a/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/EventHandlerInvoker.cs +++ b/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/EventHandlerInvoker.cs @@ -1,35 +1,40 @@ using System; using System.Collections.Concurrent; -using System.Linq; -using System.Reflection; using System.Threading.Tasks; using Volo.Abp.DependencyInjection; +using Volo.Abp.EventBus.Distributed; namespace Volo.Abp.EventBus; public class EventHandlerInvoker : IEventHandlerInvoker, ISingletonDependency { - private const string EventHandlerMethodName = "HandleEventAsync"; - private readonly ConcurrentDictionary _executorCache; + private readonly ConcurrentDictionary _cache; public EventHandlerInvoker() { - _executorCache = new ConcurrentDictionary(); + _cache = new ConcurrentDictionary(); } - public Task InvokeAsync(IEventHandler eventHandler, object eventData, Type eventType) + public async Task InvokeAsync(IEventHandler eventHandler, object eventData, Type eventType) { - var handleType = eventHandler.GetType(); - var key = $"{handleType.FullName}_{eventType.FullName}"; + if (typeof(ILocalEventHandler<>).MakeGenericType(eventType).IsInstanceOfType(eventHandler)) + { + 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 }); - } - - private static MethodInfo GetHandleEventMethodInfo(Type handleType, Type eventType) - { - 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)); + if (!typeof(ILocalEventHandler<>).MakeGenericType(eventType).IsInstanceOfType(eventHandler) && + !typeof(IDistributedEventHandler<>).MakeGenericType(eventType).IsInstanceOfType(eventHandler)) + { + throw new AbpException("The object instance is not an event handler. Object type: " + eventHandler.GetType().AssemblyQualifiedName); + } } } diff --git a/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/EventHandlerMethodExecutor.cs b/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/EventHandlerMethodExecutor.cs index 332b9af1ef..accbe513b2 100644 --- a/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/EventHandlerMethodExecutor.cs +++ b/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/EventHandlerMethodExecutor.cs @@ -1,66 +1,34 @@ using System; -using System.Collections.Generic; -using System.Linq.Expressions; -using System.Reflection; using System.Threading.Tasks; +using Volo.Abp.EventBus.Distributed; namespace Volo.Abp.EventBus; -public class EventHandlerMethodExecutor -{ - private readonly MethodExecutorAsync _executorAsync; - private delegate Task MethodExecutorAsync(IEventHandler target, object[] parameters); +public delegate Task EventHandlerMethodExecutorAsync(IEventHandler target, object parameter); - public MethodInfo MethodInfo { get; } +public interface IEventHandlerMethodExecutor +{ + EventHandlerMethodExecutorAsync ExecutorAsync { get; } +} - public TypeInfo TargetTypeInfo { get; } +public class LocalEventHandlerMethodExecutor : IEventHandlerMethodExecutor + where TEvent : class +{ + public EventHandlerMethodExecutorAsync ExecutorAsync => (target, parameter) => target.As>().HandleEventAsync(parameter.As()); - private EventHandlerMethodExecutor(MethodInfo methodInfo, TypeInfo targetTypeInfo) + public Task ExecuteAsync(IEventHandler target, TEvent parameters) { - if (methodInfo == null) - { - 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(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(castMethodCall, targetParameter, parametersParameter); - return lambda.Compile(); - + return ExecutorAsync(target, parameters); } +} - public static EventHandlerMethodExecutor Create(MethodInfo methodInfo, TypeInfo targetTypeInfo) - { - return new EventHandlerMethodExecutor(methodInfo, targetTypeInfo); - } +public class DistributedEventHandlerMethodExecutor : IEventHandlerMethodExecutor + where TEvent : class +{ + public EventHandlerMethodExecutorAsync ExecutorAsync => (target, parameter) => target.As>().HandleEventAsync(parameter.As()); - public Task ExecuteAsync(IEventHandler target, object[] parameters) + public Task ExecuteAsync(IEventHandler target, TEvent parameters) { - return _executorAsync(target, parameters); + return ExecutorAsync(target, parameters); } } diff --git a/framework/test/Volo.Abp.EventBus.Tests/Volo/Abp/EventBus/EventHandlerInvoker_Tests.cs b/framework/test/Volo.Abp.EventBus.Tests/Volo/Abp/EventBus/EventHandlerInvoker_Tests.cs index eb02114dc6..294debbb09 100644 --- a/framework/test/Volo.Abp.EventBus.Tests/Volo/Abp/EventBus/EventHandlerInvoker_Tests.cs +++ b/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()); - localHandler.MyEventDataCount.ShouldBe(1); + localHandler.MyEventDataCount.ShouldBe(2); localHandler.EntityChangedEventDataCount.ShouldBe(0); localHandler.EntityChangedEventDataCount.ShouldBe(0); } @@ -99,6 +99,7 @@ public class EventHandlerInvoker_Tests : EventBusTestBase } public class MyLocalEventHandler : ILocalEventHandler, + IDistributedEventHandler, IDistributedEventHandler>, IDistributedEventHandler> {