diff --git a/framework/src/Volo.Abp.EventBus.Abstractions/Volo/Abp/EventBus/Local/LocalEventHandlerOrderAttribute.cs b/framework/src/Volo.Abp.EventBus.Abstractions/Volo/Abp/EventBus/Local/LocalEventHandlerOrderAttribute.cs
new file mode 100644
index 0000000000..7900885e3e
--- /dev/null
+++ b/framework/src/Volo.Abp.EventBus.Abstractions/Volo/Abp/EventBus/Local/LocalEventHandlerOrderAttribute.cs
@@ -0,0 +1,17 @@
+using System;
+
+namespace Volo.Abp.EventBus.Local;
+
+[AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = true)]
+public class LocalEventHandlerOrderAttribute : Attribute
+{
+ ///
+ /// Handlers execute in ascending numeric value of the Order property.
+ ///
+ public int Order { get; set; }
+
+ public LocalEventHandlerOrderAttribute(int order)
+ {
+ Order = order;
+ }
+}
diff --git a/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Local/LocalEventBus.cs b/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Local/LocalEventBus.cs
index 9570bf80e1..d73b2f8de9 100644
--- a/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Local/LocalEventBus.cs
+++ b/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Local/LocalEventBus.cs
@@ -10,6 +10,7 @@ using Microsoft.Extensions.DependencyInjection;
using Volo.Abp.DependencyInjection;
using Volo.Abp.EventBus.Distributed;
using Volo.Abp.MultiTenancy;
+using Volo.Abp.Reflection;
using Volo.Abp.Threading;
using Volo.Abp.Uow;
@@ -138,14 +139,19 @@ public class LocalEventBus : EventBusBase, ILocalEventBus, ISingletonDependency
protected override IEnumerable GetHandlerFactories(Type eventType)
{
- var handlerFactoryList = new List();
-
+ var handlerFactoryList = new List>();
foreach (var handlerFactory in HandlerFactories.Where(hf => ShouldTriggerEventForHandler(eventType, hf.Key)))
{
- handlerFactoryList.Add(new EventTypeWithEventHandlerFactories(handlerFactory.Key, handlerFactory.Value));
+ foreach (var factory in handlerFactory.Value)
+ {
+ handlerFactoryList.Add(new Tuple(
+ factory,
+ handlerFactory.Key,
+ ReflectionHelper.GetAttributesOfMemberOrDeclaringType(factory.GetHandler().EventHandler.GetType()).FirstOrDefault()?.Order ?? 0));
+ }
}
- return handlerFactoryList.ToArray();
+ return handlerFactoryList.OrderBy(x => x.Item3).Select(x => new EventTypeWithEventHandlerFactories(x.Item2, new List {x.Item1})).ToArray();
}
private List GetOrCreateHandlerFactories(Type eventType)
diff --git a/framework/test/Volo.Abp.EventBus.Tests/Volo/Abp/EventBus/Local/EventBus_Order_Test.cs b/framework/test/Volo.Abp.EventBus.Tests/Volo/Abp/EventBus/Local/EventBus_Order_Test.cs
new file mode 100644
index 0000000000..3bf8c3a7b6
--- /dev/null
+++ b/framework/test/Volo.Abp.EventBus.Tests/Volo/Abp/EventBus/Local/EventBus_Order_Test.cs
@@ -0,0 +1,56 @@
+using System.Threading.Tasks;
+using Shouldly;
+using Volo.Abp.DependencyInjection;
+using Volo.Abp.Domain.Entities;
+using Volo.Abp.Domain.Entities.Events;
+using Xunit;
+
+namespace Volo.Abp.EventBus.Local;
+
+public class EventBus_Order_Test : EventBusTestBase
+{
+ public static string HandlerExecuteOrder { get; set; }
+
+ [Fact]
+ public async Task Handler_Should_Execute_By_Order()
+ {
+ HandlerExecuteOrder = "";
+ await LocalEventBus.PublishAsync(new MyOrderEventHandlerEventData());
+ HandlerExecuteOrder.ShouldBe("321");
+ }
+
+ public class MyOrderEventHandlerEventData
+ {
+
+ }
+
+ public class MyOrderEventHandler : ILocalEventHandler, ITransientDependency
+ {
+ public Task HandleEventAsync(MyOrderEventHandlerEventData eventData)
+ {
+ HandlerExecuteOrder += "1";
+ return Task.CompletedTask;
+ }
+ }
+
+ [LocalEventHandlerOrder(-2)]
+ public class MyOrderEventHandler2 : ILocalEventHandler, ITransientDependency
+ {
+ public Task HandleEventAsync(MyOrderEventHandlerEventData eventData)
+ {
+ HandlerExecuteOrder += "2";
+ return Task.CompletedTask;
+ }
+ }
+
+ [LocalEventHandlerOrder(-3)]
+ public class MyOrderEventHandler3 : ILocalEventHandler, ITransientDependency
+ {
+ public Task HandleEventAsync(MyOrderEventHandlerEventData eventData)
+ {
+ HandlerExecuteOrder += "3";
+ return Task.CompletedTask;
+ }
+ }
+
+}