From 77d54685c2118ab07939cb56a00ce7a35d8fa050 Mon Sep 17 00:00:00 2001 From: Weihan Li Date: Fri, 1 Mar 2024 01:35:22 +0800 Subject: [PATCH 01/10] ci: update github release create script --- .github/workflows/release.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 056689d9..a91a1254 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -27,4 +27,4 @@ jobs: env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: | - gh release create --generate-notes ${{ env.ReleaseVersion }} + gh release create ${{ env.ReleaseVersion }} --generate-notes --target ${{ env.GITHUB_SHA }} ./artifacts/packages/*.nupkg From 2e8cc6ce3369203cce6536ec7eb7d6128428f5ab Mon Sep 17 00:00:00 2001 From: Weihan Li Date: Fri, 1 Mar 2024 17:50:07 +0800 Subject: [PATCH 02/10] docs: Update README.md update azure pipeline build badge --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 50f2acf0..0b15fc71 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ [![WeihanLi.Common Latest](https://img.shields.io/nuget/vpre/WeihanLi.Common)](https://www.nuget.org/packages/WeihanLi.Common/absoluteLatest) -[![Azure Pipelines Build Status](https://weihanli.visualstudio.com/Pipelines/_apis/build/status/WeihanLi.WeihanLi.Common?branchName=dev)](https://weihanli.visualstudio.com/Pipelines/_build/latest?definitionId=16&branchName=dev) +[![Azure Pipelines Build Status](https://weihanli.visualstudio.com/Pipelines/_apis/build/status/WeihanLi.WeihanLi.Common?branchName=master)](https://weihanli.visualstudio.com/Pipelines/_build/latest?definitionId=16&branchName=master) [![Github Actions Build Status](https://github.com/WeihanLi/WeihanLi.Common/actions/workflows/default.yml/badge.svg)](https://github.com/WeihanLi/WeihanLi.Common/actions/workflows/default.yml) From cd48259a304e19d516a05392edd05d4d51392b8a Mon Sep 17 00:00:00 2001 From: Weihan Li Date: Tue, 5 Mar 2024 13:43:52 +0800 Subject: [PATCH 03/10] feat: update TaskHelper.ToTask return type to Task --- src/WeihanLi.Common/Helpers/TaskHelper.cs | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/src/WeihanLi.Common/Helpers/TaskHelper.cs b/src/WeihanLi.Common/Helpers/TaskHelper.cs index 2ae2893b..a58f1f06 100644 --- a/src/WeihanLi.Common/Helpers/TaskHelper.cs +++ b/src/WeihanLi.Common/Helpers/TaskHelper.cs @@ -5,18 +5,13 @@ namespace WeihanLi.Common.Helpers; public static class TaskHelper { - public static ValueTask ToTask(object? obj) + public static Task ToTask(object? obj) { var task = obj switch { - ValueTask vt => vt, - Task t => new ValueTask(t), - _ => -#if NET6_0_OR_GREATER - ValueTask.CompletedTask -#else - default -#endif + ValueTask vt => vt.AsTask(), + Task t => t, + _ => Task.CompletedTask }; return task; } From cc1dfe7c09481d793395e3c00f2cc27cb7a26a5b Mon Sep 17 00:00:00 2001 From: Weihan Li Date: Tue, 5 Mar 2024 14:47:08 +0800 Subject: [PATCH 04/10] build: bump package version --- build/version.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/version.props b/build/version.props index 590bdc99..ad4f8299 100644 --- a/build/version.props +++ b/build/version.props @@ -2,7 +2,7 @@ 1 0 - 63 + 64 $(VersionMajor).$(VersionMinor).$(VersionPatch) From 86de0fe4a2e73bb1164c4a244ce412d906148342 Mon Sep 17 00:00:00 2001 From: Weihan Li Date: Tue, 5 Mar 2024 23:12:38 +0800 Subject: [PATCH 05/10] refactor: refactor events contributes to #185 --- .../AspNetCoreSample/Events/PageViewEvent.cs | 4 +-- samples/AspNetCoreSample/Startup.cs | 6 ++-- samples/DotNetCoreSample/EventTest.cs | 10 +++--- .../Event/DelegateEventHandler.cs | 8 ++--- src/WeihanLi.Common/Event/EventBase.cs | 8 +++++ src/WeihanLi.Common/Event/EventBus.cs | 4 +-- .../Event/EventBusExtensions.cs | 12 +++---- src/WeihanLi.Common/Event/EventHandler.cs | 35 +++++++++++++++---- src/WeihanLi.Common/Event/EventProperties.cs | 10 ++++++ .../Event/EventQueueInMemory.cs | 27 ++++++++++++-- .../Event/EventQueuePublisher.cs | 11 +----- .../Event/IEventHandlerFactory.cs | 2 +- src/WeihanLi.Common/Event/IEventPublisher.cs | 10 +----- src/WeihanLi.Common/Event/IEventQueue.cs | 4 +-- src/WeihanLi.Common/Event/IEventSubscriber.cs | 2 +- .../AspectTest/ProxyFactoryTest.cs | 8 ++--- .../AspectTest/ServiceCollectionBuildTest.cs | 7 ++-- .../ServiceContainerBuilderBuildTest.cs | 1 - .../EventsTest/EventBaseTest.cs | 4 +-- .../EventsTest/EventBusTest.cs | 6 ++-- 20 files changed, 111 insertions(+), 68 deletions(-) create mode 100644 src/WeihanLi.Common/Event/EventProperties.cs diff --git a/samples/AspNetCoreSample/Events/PageViewEvent.cs b/samples/AspNetCoreSample/Events/PageViewEvent.cs index b8b26716..ac469ee0 100644 --- a/samples/AspNetCoreSample/Events/PageViewEvent.cs +++ b/samples/AspNetCoreSample/Events/PageViewEvent.cs @@ -2,7 +2,7 @@ namespace AspNetCoreSample.Events; -public class PageViewEvent : EventBase +public class PageViewEvent { public string? Path { get; set; } } @@ -11,7 +11,7 @@ public class PageViewEventHandler : EventHandlerBase { public static int Count; - public override Task Handle(PageViewEvent @event) + public override Task Handle(PageViewEvent @event, EventProperties eventProperties) { Interlocked.Increment(ref Count); return Task.CompletedTask; diff --git a/samples/AspNetCoreSample/Startup.cs b/samples/AspNetCoreSample/Startup.cs index 9d14f57f..98eb9b48 100644 --- a/samples/AspNetCoreSample/Startup.cs +++ b/samples/AspNetCoreSample/Startup.cs @@ -42,16 +42,16 @@ public void Configure(IApplicationBuilder app, IWebHostEnvironment env) } // pageView middleware - app.Use((context, next) => + app.Use(async (context, next) => { var eventPublisher = context.RequestServices .GetRequiredService(); - eventPublisher.Publish(new PageViewEvent() + await eventPublisher.PublishAsync(new PageViewEvent() { Path = context.Request.Path.Value ?? "", }); - return next(); + await next(); }); app.UseHttpLogging(); app.UseRouting(); diff --git a/samples/DotNetCoreSample/EventTest.cs b/samples/DotNetCoreSample/EventTest.cs index 5e7274a1..2774aa6e 100644 --- a/samples/DotNetCoreSample/EventTest.cs +++ b/samples/DotNetCoreSample/EventTest.cs @@ -8,7 +8,7 @@ namespace DotNetCoreSample; internal class EventTest { - public static void MainTest() + public static async Task MainTest() { var eventBus = DependencyResolver.ResolveRequiredService(); @@ -18,11 +18,11 @@ public static void MainTest() eventBus.Subscribe(); eventBus.Subscribe>(); // could be used for eventLogging - eventBus.Publish(new CounterEvent { Counter = 1 }); + await eventBus.PublishAsync(new CounterEvent { Counter = 1 }); eventBus.UnSubscribe(); // eventBus.Unsubscribe>(); - eventBus.Publish(new CounterEvent { Counter = 2 }); + await eventBus.PublishAsync(new CounterEvent { Counter = 2 }); } } @@ -33,7 +33,7 @@ public class CounterEvent : EventBase internal class CounterEventHandler1 : EventHandlerBase { - public override Task Handle(CounterEvent @event) + public override Task Handle(CounterEvent @event, EventProperties eventProperties) { LogHelper.GetLogger().Info($"Event Info: {@event.ToJson()}, Handler Type:{GetType().FullName}"); return Task.CompletedTask; @@ -42,7 +42,7 @@ public override Task Handle(CounterEvent @event) internal class CounterEventHandler2 : EventHandlerBase { - public override Task Handle(CounterEvent @event) + public override Task Handle(CounterEvent @event, EventProperties eventProperties) { LogHelper.GetLogger().Info($"Event Info: {@event.ToJson()}, Handler Type:{GetType().FullName}"); return Task.CompletedTask; diff --git a/src/WeihanLi.Common/Event/DelegateEventHandler.cs b/src/WeihanLi.Common/Event/DelegateEventHandler.cs index 6981960d..37970520 100644 --- a/src/WeihanLi.Common/Event/DelegateEventHandler.cs +++ b/src/WeihanLi.Common/Event/DelegateEventHandler.cs @@ -7,13 +7,13 @@ namespace WeihanLi.Common.Event; public static class DelegateEventHandler { - public static DelegateEventHandler FromAction(Action action) where TEvent : class, IEventBase => new(action); + public static DelegateEventHandler FromAction(Action action) where TEvent : class => new(action); - public static DelegateEventHandler FromFunc(Func func) where TEvent : class, IEventBase => new(func); + public static DelegateEventHandler FromFunc(Func func) where TEvent : class => new(func); } public sealed class DelegateEventHandler : EventHandlerBase - where TEvent : class, IEventBase + where TEvent : class { private readonly Func _func; @@ -28,7 +28,7 @@ public DelegateEventHandler(Func func) _func = Guard.NotNull(func); } - public override Task Handle(TEvent @event) + public override Task Handle(TEvent @event, EventProperties eventProperties) { return _func.Invoke(@event); } diff --git a/src/WeihanLi.Common/Event/EventBase.cs b/src/WeihanLi.Common/Event/EventBase.cs index 5fcfc146..dafbb926 100644 --- a/src/WeihanLi.Common/Event/EventBase.cs +++ b/src/WeihanLi.Common/Event/EventBase.cs @@ -52,6 +52,14 @@ protected EventBase(string eventId, DateTimeOffset eventAt) } } +internal sealed class EventWrapper : IEventBase +{ + public required T Data { get; init; } + public EventProperties Properties { get; set; } + public DateTimeOffset EventAt => Properties.EventAt; + public string EventId => Properties.EventId; +} + public static class EventBaseExtensions { private static readonly JsonSerializerSettings EventSerializerSettings = JsonSerializeExtension.SerializerSettingsWith(s => diff --git a/src/WeihanLi.Common/Event/EventBus.cs b/src/WeihanLi.Common/Event/EventBus.cs index a0b93cff..1482f351 100644 --- a/src/WeihanLi.Common/Event/EventBus.cs +++ b/src/WeihanLi.Common/Event/EventBus.cs @@ -16,7 +16,7 @@ public sealed class EventBus(IEventSubscriptionManager subscriptionManager, IEve private readonly IEventSubscriptionManager _subscriptionManager = subscriptionManager; private readonly IEventHandlerFactory _eventHandlerFactory = eventHandlerFactory; - public bool Publish(TEvent @event) where TEvent : class, IEventBase + public bool Publish(TEvent @event) where TEvent : class { var handlers = _eventHandlerFactory.GetHandlers(); if (handlers.Count > 0) @@ -39,7 +39,7 @@ public bool Publish(TEvent @event) where TEvent : class, IEventBase return false; } - public async Task PublishAsync(TEvent @event) where TEvent : class, IEventBase + public async Task PublishAsync(TEvent @event) where TEvent : class { var handlers = _eventHandlerFactory.GetHandlers(); if (handlers.Count > 0) diff --git a/src/WeihanLi.Common/Event/EventBusExtensions.cs b/src/WeihanLi.Common/Event/EventBusExtensions.cs index e53197b7..b010e520 100644 --- a/src/WeihanLi.Common/Event/EventBusExtensions.cs +++ b/src/WeihanLi.Common/Event/EventBusExtensions.cs @@ -5,6 +5,7 @@ using Microsoft.Extensions.DependencyInjection.Extensions; using System.Diagnostics.CodeAnalysis; using System.Reflection; +using WeihanLi.Extensions; namespace WeihanLi.Common.Event; @@ -36,7 +37,7 @@ public static IEventBuilder AddEvents(this IServiceCollection services) } public static IEventBuilder AddEventHandler(this IEventBuilder eventBuilder, ServiceLifetime serviceLifetime = ServiceLifetime.Transient) - where TEvent : class, IEventBase + where TEvent : class where TEventHandler : class, IEventHandler { eventBuilder.Services.TryAddEnumerable(new ServiceDescriptor(typeof(IEventHandler), typeof(TEventHandler), serviceLifetime)); @@ -44,7 +45,7 @@ public static IEventBuilder AddEvents(this IServiceCollection services) } public static IEventBuilder AddEventHandler(this IEventBuilder eventBuilder, IEventHandler eventHandler) - where TEvent : class, IEventBase + where TEvent : class { eventBuilder.Services.TryAddEnumerable(new ServiceDescriptor(typeof(IEventHandler), eventHandler)); return eventBuilder; @@ -53,8 +54,7 @@ public static IEventBuilder AddEventHandler(this IEventBuilder eventBuil [RequiresUnreferencedCode("Assembly.GetTypes() requires unreferenced code")] public static IEventBuilder RegisterEventHandlers(this IEventBuilder builder, Func? filter = null, ServiceLifetime serviceLifetime = ServiceLifetime.Singleton, params Assembly[] assemblies) { - Guard.NotNull(assemblies, nameof(assemblies)); - if (assemblies.Length == 0) + if (assemblies.IsNullOrEmpty()) { assemblies = Helpers.ReflectHelper.GetAssemblies(); } @@ -67,12 +67,12 @@ public static IEventBuilder RegisterEventHandlers(this IEventBuilder builder, Fu { handlerTypes = handlerTypes.Where(filter); } - + foreach (var handlerType in handlerTypes) { foreach (var implementedInterface in handlerType.GetTypeInfo().ImplementedInterfaces) { - if (implementedInterface.IsGenericType && typeof(IEventBase).IsAssignableFrom(implementedInterface.GenericTypeArguments[0])) + if (implementedInterface.IsGenericType && typeof(IEventHandler<>) == implementedInterface.GetGenericTypeDefinition()) { builder.Services.TryAddEnumerable(new ServiceDescriptor(implementedInterface, handlerType, serviceLifetime)); } diff --git a/src/WeihanLi.Common/Event/EventHandler.cs b/src/WeihanLi.Common/Event/EventHandler.cs index 14a10e86..4afc14a8 100644 --- a/src/WeihanLi.Common/Event/EventHandler.cs +++ b/src/WeihanLi.Common/Event/EventHandler.cs @@ -11,18 +11,34 @@ public interface IEventHandler Task Handle(object eventData); } -public interface IEventHandler : IEventHandler where TEvent : class, IEventBase +public interface IEventHandler : IEventHandler where TEvent : class { /// /// Handler event /// /// event - Task Handle(TEvent @event); + /// eventProperties + Task Handle(TEvent @event, EventProperties eventProperties); } -public abstract class EventHandlerBase : IEventHandler where TEvent : class, IEventBase +public abstract class EventHandlerBase : IEventHandler where TEvent : class { - public abstract Task Handle(TEvent @event); + public abstract Task Handle(TEvent @event, EventProperties eventProperties); + + private Task Handle(TEvent @event) + { + return Handle(@event, @event is IEventBase eventBase ? + new EventProperties + { + EventId = eventBase.EventId, + EventAt = eventBase.EventAt, + }: + new EventProperties + { + EventId = Guid.NewGuid().ToString(), + EventAt = DateTimeOffset.UtcNow + }); + } public virtual Task Handle(object eventData) { @@ -32,13 +48,17 @@ public virtual Task Handle(object eventData) { case TEvent data: return Handle(data); + case JObject jObject: { + var eventWrapper = jObject.ToObject>(); + if (eventWrapper != null) + return Handle(eventWrapper.Data, eventWrapper.Properties); + var @event = jObject.ToObject(); if (@event != null) - { return Handle(@event); - } + break; } case string eventDataJson: @@ -46,5 +66,8 @@ public virtual Task Handle(object eventData) } throw new ArgumentException(@$"Unsupported event DataType:{eventData.GetType()}", nameof(eventData)); + + + } } diff --git a/src/WeihanLi.Common/Event/EventProperties.cs b/src/WeihanLi.Common/Event/EventProperties.cs new file mode 100644 index 00000000..d1452d8a --- /dev/null +++ b/src/WeihanLi.Common/Event/EventProperties.cs @@ -0,0 +1,10 @@ +// Copyright (c) Weihan Li. All rights reserved. +// Licensed under the Apache license. + +namespace WeihanLi.Common.Event; + +public sealed class EventProperties: Dictionary, IEventBase +{ + public DateTimeOffset EventAt { get; init; } + public string EventId { get; init; } +} diff --git a/src/WeihanLi.Common/Event/EventQueueInMemory.cs b/src/WeihanLi.Common/Event/EventQueueInMemory.cs index 749efffe..89bc5ced 100644 --- a/src/WeihanLi.Common/Event/EventQueueInMemory.cs +++ b/src/WeihanLi.Common/Event/EventQueueInMemory.cs @@ -13,14 +13,35 @@ public sealed class EventQueueInMemory : IEventQueue public Task> GetQueuesAsync() => Task.FromResult(GetQueues()); - public bool Enqueue(string queueName, TEvent @event) where TEvent : class, IEventBase + public bool Enqueue(string queueName, TEvent @event) where TEvent : class { + var internalEvent = @event switch + { + IEventBase eventBase => new EventWrapper() + { + Data = @event, + Properties = new EventProperties + { + EventId = eventBase.EventId, + EventAt = eventBase.EventAt + } + }, + _ => new EventWrapper() + { + Data = @event, + Properties = new EventProperties + { + EventId = Guid.NewGuid().ToString(), + EventAt = DateTimeOffset.UtcNow + } + } + }; var queue = _eventQueues.GetOrAdd(queueName, _ => new ConcurrentQueue()); - queue.Enqueue(@event); + queue.Enqueue(internalEvent); return true; } - public Task EnqueueAsync(string queueName, TEvent @event) where TEvent : class, IEventBase => Task.FromResult(Enqueue(queueName, @event)); + public Task EnqueueAsync(string queueName, TEvent @event) where TEvent : class => Task.FromResult(Enqueue(queueName, @event)); public IEventBase? Dequeue(string queueName) { diff --git a/src/WeihanLi.Common/Event/EventQueuePublisher.cs b/src/WeihanLi.Common/Event/EventQueuePublisher.cs index f3215d43..fd91aeb1 100644 --- a/src/WeihanLi.Common/Event/EventQueuePublisher.cs +++ b/src/WeihanLi.Common/Event/EventQueuePublisher.cs @@ -11,17 +11,8 @@ public class EventQueuePublisher(IEventQueue eventQueue, IOptions(TEvent @event) - where TEvent : class, IEventBase - { - var queueName = _options.EventQueueNameResolver.Invoke(@event.GetType()) ?? "events"; - - return _eventQueue.EnqueueAsync(queueName, @event).ConfigureAwait(false) - .GetAwaiter().GetResult(); - } - public virtual Task PublishAsync(TEvent @event) - where TEvent : class, IEventBase + where TEvent : class { var queueName = _options.EventQueueNameResolver.Invoke(@event.GetType()) ?? "events"; return _eventQueue.EnqueueAsync(queueName, @event); diff --git a/src/WeihanLi.Common/Event/IEventHandlerFactory.cs b/src/WeihanLi.Common/Event/IEventHandlerFactory.cs index 9d8c3f92..5784ddbc 100644 --- a/src/WeihanLi.Common/Event/IEventHandlerFactory.cs +++ b/src/WeihanLi.Common/Event/IEventHandlerFactory.cs @@ -11,7 +11,7 @@ public interface IEventHandlerFactory public static class EventHandlerFactoryExtensions { public static ICollection> GetHandlers(this IEventHandlerFactory eventHandlerFactory) - where TEvent : class, IEventBase + where TEvent : class { return eventHandlerFactory.GetHandlers(typeof(TEvent)) .Cast>() diff --git a/src/WeihanLi.Common/Event/IEventPublisher.cs b/src/WeihanLi.Common/Event/IEventPublisher.cs index ee160c29..52710f21 100644 --- a/src/WeihanLi.Common/Event/IEventPublisher.cs +++ b/src/WeihanLi.Common/Event/IEventPublisher.cs @@ -5,19 +5,11 @@ namespace WeihanLi.Common.Event; public interface IEventPublisher { - /// - /// publish an event - /// - /// event type - /// event data - /// whether the operation succeed - bool Publish(TEvent @event) where TEvent : class, IEventBase; - /// /// publish an event async /// /// event type /// event data /// whether the operation succeed - Task PublishAsync(TEvent @event) where TEvent : class, IEventBase; + Task PublishAsync(TEvent @event) where TEvent : class; } diff --git a/src/WeihanLi.Common/Event/IEventQueue.cs b/src/WeihanLi.Common/Event/IEventQueue.cs index 281b3f4d..5cd1b70c 100644 --- a/src/WeihanLi.Common/Event/IEventQueue.cs +++ b/src/WeihanLi.Common/Event/IEventQueue.cs @@ -8,7 +8,7 @@ public interface IEventQueue Task> GetQueuesAsync(); Task EnqueueAsync(string queueName, TEvent @event) - where TEvent : class, IEventBase; + where TEvent : class; Task DequeueAsync(string queueName); } @@ -18,7 +18,7 @@ public static class EventQueueExtensions private const string DefaultQueueName = "events"; public static Task EnqueueAsync(this IEventQueue eventQueue, TEvent @event) - where TEvent : class, IEventBase + where TEvent : class { return eventQueue.EnqueueAsync(DefaultQueueName, @event); } diff --git a/src/WeihanLi.Common/Event/IEventSubscriber.cs b/src/WeihanLi.Common/Event/IEventSubscriber.cs index 9305edee..a92347f5 100644 --- a/src/WeihanLi.Common/Event/IEventSubscriber.cs +++ b/src/WeihanLi.Common/Event/IEventSubscriber.cs @@ -48,7 +48,7 @@ public static class EventSubscriberExtensions /// whether the operation success public static bool Subscribe(this IEventSubscriber subscriber) where TEventHandler : class, IEventHandler - where TEvent : class, IEventBase + where TEvent : class { return subscriber.Subscribe(typeof(TEvent), typeof(TEventHandler)); } diff --git a/test/WeihanLi.Common.Test/AspectTest/ProxyFactoryTest.cs b/test/WeihanLi.Common.Test/AspectTest/ProxyFactoryTest.cs index d13285f1..dc5e0b50 100644 --- a/test/WeihanLi.Common.Test/AspectTest/ProxyFactoryTest.cs +++ b/test/WeihanLi.Common.Test/AspectTest/ProxyFactoryTest.cs @@ -70,18 +70,18 @@ public void CreateInstanceWithArguments() var eventPublisherProxy = _proxyFactory.CreateProxy(); Assert.NotNull(eventPublisherProxy); Assert.True(eventPublisherProxy.GetType().Namespace?.StartsWith(NamespacePrefix)); - eventPublisherProxy.Publish(new TestEvent()); + eventPublisherProxy.PublishAsync(new TestEvent()).Wait(); eventPublisherProxy = _proxyFactory.CreateProxy(); Assert.NotNull(eventPublisherProxy); Assert.True(eventPublisherProxy.GetType().Namespace?.StartsWith(NamespacePrefix)); - eventPublisherProxy.Publish(new TestEvent()); + eventPublisherProxy.PublishAsync(new TestEvent()).Wait(); var options = new OptionsWrapper(new EventQueuePublisherOptions()); eventPublisherProxy = _proxyFactory.CreateProxy(options); Assert.NotNull(eventPublisherProxy); Assert.True(eventPublisherProxy.GetType().Namespace?.StartsWith(NamespacePrefix)); - eventPublisherProxy.Publish(new TestEvent()); + eventPublisherProxy.PublishAsync(new TestEvent()).Wait(); } [Fact] @@ -91,7 +91,7 @@ public void CreateInstanceOfInterfaceWithInherit() Assert.NotNull(eventBusProxy); Assert.True(eventBusProxy.GetType().Namespace?.StartsWith(NamespacePrefix)); - eventBusProxy.Publish(new TestEvent()); + eventBusProxy.PublishAsync(new TestEvent()).Wait(); } [Fact] diff --git a/test/WeihanLi.Common.Test/AspectTest/ServiceCollectionBuildTest.cs b/test/WeihanLi.Common.Test/AspectTest/ServiceCollectionBuildTest.cs index 9d6450dc..7b1b59b1 100644 --- a/test/WeihanLi.Common.Test/AspectTest/ServiceCollectionBuildTest.cs +++ b/test/WeihanLi.Common.Test/AspectTest/ServiceCollectionBuildTest.cs @@ -12,7 +12,7 @@ public class ServiceCollectionBuildTest { public class TestGenericEventHandler : EventHandlerBase where TEvent : class, IEventBase { - public override Task Handle(TEvent @event) => Task.CompletedTask; + public override Task Handle(TEvent @event, EventProperties eventProperties) => Task.CompletedTask; } private readonly IServiceProvider _serviceProvider; @@ -103,15 +103,14 @@ public async Task ClassTest() } [Fact] - public async void GenericMethodTest() + public async Task GenericMethodTest() { var publisher = _serviceProvider.GetRequiredService(); Assert.NotNull(publisher); var publisherType = publisher.GetType(); Assert.True(publisherType.IsSealed); Assert.True(publisherType.Assembly.IsDynamic); - publisher.Publish(new TestEvent()); - + await publisher.PublishAsync(new TestEvent()); } diff --git a/test/WeihanLi.Common.Test/AspectTest/ServiceContainerBuilderBuildTest.cs b/test/WeihanLi.Common.Test/AspectTest/ServiceContainerBuilderBuildTest.cs index 777f3107..5b03dc75 100644 --- a/test/WeihanLi.Common.Test/AspectTest/ServiceContainerBuilderBuildTest.cs +++ b/test/WeihanLi.Common.Test/AspectTest/ServiceContainerBuilderBuildTest.cs @@ -107,7 +107,6 @@ public async Task GenericMethodTest() var publisherType = publisher.GetType(); Assert.True(publisherType.IsSealed); Assert.True(publisherType.Assembly.IsDynamic); - publisher.Publish(new TestEvent()); await publisher.PublishAsync(new TestEvent()); } diff --git a/test/WeihanLi.Common.Test/EventsTest/EventBaseTest.cs b/test/WeihanLi.Common.Test/EventsTest/EventBaseTest.cs index 8cf65caa..cd815875 100644 --- a/test/WeihanLi.Common.Test/EventsTest/EventBaseTest.cs +++ b/test/WeihanLi.Common.Test/EventsTest/EventBaseTest.cs @@ -13,7 +13,7 @@ public class TestEventHandler : EventHandlerBase { public static int Count; - public override Task Handle(TestEvent @event) + public override Task Handle(TestEvent @event, EventProperties eventProperties) { Count++; return Task.CompletedTask; @@ -49,7 +49,7 @@ public void EventMessageExtensionsTest() var deserializedEvent = eventFromMsg as TestEvent; Assert.NotNull(deserializedEvent); - Assert.Equal(testEvent.EventId, deserializedEvent!.EventId); + Assert.Equal(testEvent.EventId, deserializedEvent.EventId); Assert.Equal(testEvent.EventAt, deserializedEvent.EventAt); Assert.Equal(testEvent.Name, deserializedEvent.Name); } diff --git a/test/WeihanLi.Common.Test/EventsTest/EventBusTest.cs b/test/WeihanLi.Common.Test/EventsTest/EventBusTest.cs index 29d8be8f..8f4f1c86 100644 --- a/test/WeihanLi.Common.Test/EventsTest/EventBusTest.cs +++ b/test/WeihanLi.Common.Test/EventsTest/EventBusTest.cs @@ -45,7 +45,7 @@ public class TestEvent1 : EventBase public class TestEventHandler1 : EventHandlerBase { - public override Task Handle(TestEvent @event) + public override Task Handle(TestEvent @event, EventProperties eventProperties) { Interlocked.Increment(ref _counter); return Task.CompletedTask; @@ -54,7 +54,7 @@ public override Task Handle(TestEvent @event) public class TestEventHandler2 : EventHandlerBase { - public override Task Handle(TestEvent @event) + public override Task Handle(TestEvent @event, EventProperties eventProperties) { Interlocked.Increment(ref _counter); return Task.CompletedTask; @@ -64,7 +64,7 @@ public override Task Handle(TestEvent @event) public class TestEventHandler3 : EventHandlerBase where TEvent : class, IEventBase { - public override Task Handle(TEvent @event) + public override Task Handle(TEvent @event, EventProperties eventProperties) { if (@event.GetType() == typeof(TestEvent)) { From 4a4f4e35c05d521e454bbe31e33021f491a38162 Mon Sep 17 00:00:00 2001 From: Weihan Li Date: Tue, 5 Mar 2024 23:48:50 +0800 Subject: [PATCH 06/10] test: update test case --- test/WeihanLi.Common.Test/AspectTest/ProxyFactoryTest.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/WeihanLi.Common.Test/AspectTest/ProxyFactoryTest.cs b/test/WeihanLi.Common.Test/AspectTest/ProxyFactoryTest.cs index dc5e0b50..a8f0c826 100644 --- a/test/WeihanLi.Common.Test/AspectTest/ProxyFactoryTest.cs +++ b/test/WeihanLi.Common.Test/AspectTest/ProxyFactoryTest.cs @@ -91,7 +91,7 @@ public void CreateInstanceOfInterfaceWithInherit() Assert.NotNull(eventBusProxy); Assert.True(eventBusProxy.GetType().Namespace?.StartsWith(NamespacePrefix)); - eventBusProxy.PublishAsync(new TestEvent()).Wait(); + // eventBusProxy.PublishAsync(new TestEvent()).Wait(); } [Fact] From 079dca3e6303ed610a1c6318ece54fdf0f345653 Mon Sep 17 00:00:00 2001 From: Weihan Li Date: Tue, 5 Mar 2024 23:51:06 +0800 Subject: [PATCH 07/10] refactor: add debugger step through --- src/WeihanLi.Common/Extensions/CoreExtension.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/WeihanLi.Common/Extensions/CoreExtension.cs b/src/WeihanLi.Common/Extensions/CoreExtension.cs index 85151339..fc399a3c 100644 --- a/src/WeihanLi.Common/Extensions/CoreExtension.cs +++ b/src/WeihanLi.Common/Extensions/CoreExtension.cs @@ -1562,6 +1562,7 @@ public static int Sign(this int value) /// successCode /// /// Exception when exitCode not match the successCode + [System.Diagnostics.DebuggerStepThrough] public static int EnsureSuccessExitCode(this int exitCode, int successCode = 0) { if (exitCode != 0) From 09a1dce8161c6f8a3da275b84fc1b28e5a2c8680 Mon Sep 17 00:00:00 2001 From: Weihan Li Date: Thu, 7 Mar 2024 00:17:54 +0800 Subject: [PATCH 08/10] refactor: events refactoring v2 --- .../AspNetCoreSample/Events/EventConsumer.cs | 5 +- src/WeihanLi.Common/Event/EventBase.cs | 12 +++-- src/WeihanLi.Common/Event/EventBus.cs | 39 ++++++-------- .../Event/EventBusExtensions.cs | 3 ++ src/WeihanLi.Common/Event/EventHandler.cs | 36 +++---------- src/WeihanLi.Common/Event/EventProperties.cs | 5 +- .../Event/EventQueueInMemory.cs | 53 +++++++++---------- .../Event/EventQueuePublisher.cs | 22 ++++++-- src/WeihanLi.Common/Event/IEventPublisher.cs | 3 +- src/WeihanLi.Common/Event/IEventQueue.cs | 13 ++--- .../Extensions/TaskExtension.cs | 4 ++ .../AspectTest/ProxyFactoryTest.cs | 4 +- .../AspectTest/ServiceCollectionBuildTest.cs | 2 +- .../ServiceContainerBuilderBuildTest.cs | 2 +- 14 files changed, 99 insertions(+), 104 deletions(-) diff --git a/samples/AspNetCoreSample/Events/EventConsumer.cs b/samples/AspNetCoreSample/Events/EventConsumer.cs index aa997819..d244e9d7 100644 --- a/samples/AspNetCoreSample/Events/EventConsumer.cs +++ b/samples/AspNetCoreSample/Events/EventConsumer.cs @@ -19,14 +19,13 @@ protected override async Task ExecuteAsync(CancellationToken stoppingToken) { await queues.Select(async q => { - var @event = await _eventQueue.DequeueAsync(q); - if (null != @event) + if (await _eventQueue.TryDequeueAsync(q, out var @event, out var properties)) { var handlers = _eventHandlerFactory.GetHandlers(@event.GetType()); if (handlers.Count > 0) { await handlers - .Select(h => h.Handle(@event)) + .Select(h => h.Handle(@event, properties)) .WhenAll() ; } diff --git a/src/WeihanLi.Common/Event/EventBase.cs b/src/WeihanLi.Common/Event/EventBase.cs index dafbb926..7c31f11f 100644 --- a/src/WeihanLi.Common/Event/EventBase.cs +++ b/src/WeihanLi.Common/Event/EventBase.cs @@ -52,12 +52,18 @@ protected EventBase(string eventId, DateTimeOffset eventAt) } } -internal sealed class EventWrapper : IEventBase +internal interface IEventWrapper : IEventBase +{ + object Data { get; } +} + +internal sealed class EventWrapper : IEventWrapper { public required T Data { get; init; } - public EventProperties Properties { get; set; } + object IEventWrapper.Data => Data!; + public required EventProperties Properties { get; init; } public DateTimeOffset EventAt => Properties.EventAt; - public string EventId => Properties.EventId; + public string EventId => Properties.EventId!; } public static class EventBaseExtensions diff --git a/src/WeihanLi.Common/Event/EventBus.cs b/src/WeihanLi.Common/Event/EventBus.cs index 1482f351..747d110d 100644 --- a/src/WeihanLi.Common/Event/EventBus.cs +++ b/src/WeihanLi.Common/Event/EventBus.cs @@ -1,6 +1,8 @@ // Copyright (c) Weihan Li. All rights reserved. // Licensed under the Apache license. +using System.Diagnostics; +using WeihanLi.Common.Helpers; using WeihanLi.Common.Logging; using WeihanLi.Extensions; @@ -16,38 +18,29 @@ public sealed class EventBus(IEventSubscriptionManager subscriptionManager, IEve private readonly IEventSubscriptionManager _subscriptionManager = subscriptionManager; private readonly IEventHandlerFactory _eventHandlerFactory = eventHandlerFactory; - public bool Publish(TEvent @event) where TEvent : class + public async Task PublishAsync(TEvent @event, EventProperties? properties) where TEvent : class { - var handlers = _eventHandlerFactory.GetHandlers(); - if (handlers.Count > 0) + properties ??= new(); + if (string.IsNullOrEmpty(properties.EventId)) { - var handlerTasks = new Task[handlers.Count]; - - handlers.ForEach((handler, index) => - { - handlerTasks[index] = handler.Handle(@event).ContinueWith(r => - { - Logger.Error(r.Exception?.Unwrap(), - $"handle event [{typeof(TEvent).FullName}] error, eventHandlerType:{handler.GetType().FullName}"); - }, TaskContinuationOptions.OnlyOnFaulted); - }); - - _ = handlerTasks.WhenAllSafely().ConfigureAwait(false); - - return true; + properties.EventId = Guid.NewGuid().ToString(); + } + if (properties.EventAt == default) + { + properties.EventAt = DateTimeOffset.Now; + } + using var activity = DiagnosticHelper.ActivitySource.StartActivity(); + if (string.IsNullOrEmpty(properties.TraceId) && Activity.Current != null) + { + properties.TraceId = Activity.Current.TraceId.ToString(); } - return false; - } - - public async Task PublishAsync(TEvent @event) where TEvent : class - { var handlers = _eventHandlerFactory.GetHandlers(); if (handlers.Count > 0) { var handlerTasks = new Task[handlers.Count]; handlers.ForEach((handler, index) => { - handlerTasks[index] = handler.Handle(@event).ContinueWith(r => + handlerTasks[index] = handler.Handle(@event, properties).ContinueWith(r => { Logger.Error(r.Exception?.Unwrap(), $"handle event [{typeof(TEvent).FullName}] error, eventHandlerType:{handler.GetType().FullName}"); diff --git a/src/WeihanLi.Common/Event/EventBusExtensions.cs b/src/WeihanLi.Common/Event/EventBusExtensions.cs index b010e520..fc840732 100644 --- a/src/WeihanLi.Common/Event/EventBusExtensions.cs +++ b/src/WeihanLi.Common/Event/EventBusExtensions.cs @@ -81,4 +81,7 @@ public static IEventBuilder RegisterEventHandlers(this IEventBuilder builder, Fu return builder; } + + public static Task PublishAsync(this IEventPublisher eventPublisher, TEvent @event) where TEvent : class + => eventPublisher.PublishAsync(@event, null); } diff --git a/src/WeihanLi.Common/Event/EventHandler.cs b/src/WeihanLi.Common/Event/EventHandler.cs index 4afc14a8..5d77cd4f 100644 --- a/src/WeihanLi.Common/Event/EventHandler.cs +++ b/src/WeihanLi.Common/Event/EventHandler.cs @@ -8,7 +8,7 @@ namespace WeihanLi.Common.Event; public interface IEventHandler { - Task Handle(object eventData); + Task Handle(object eventData, EventProperties properties); } public interface IEventHandler : IEventHandler where TEvent : class @@ -17,57 +17,35 @@ public interface IEventHandler : IEventHandler where TEvent : class /// Handler event /// /// event - /// eventProperties - Task Handle(TEvent @event, EventProperties eventProperties); + /// eventProperties + Task Handle(TEvent @event, EventProperties properties); } public abstract class EventHandlerBase : IEventHandler where TEvent : class { public abstract Task Handle(TEvent @event, EventProperties eventProperties); - - private Task Handle(TEvent @event) - { - return Handle(@event, @event is IEventBase eventBase ? - new EventProperties - { - EventId = eventBase.EventId, - EventAt = eventBase.EventAt, - }: - new EventProperties - { - EventId = Guid.NewGuid().ToString(), - EventAt = DateTimeOffset.UtcNow - }); - } - public virtual Task Handle(object eventData) + public virtual Task Handle(object eventData, EventProperties properties) { Guard.NotNull(eventData); switch (eventData) { case TEvent data: - return Handle(data); + return Handle(data, properties); case JObject jObject: { - var eventWrapper = jObject.ToObject>(); - if (eventWrapper != null) - return Handle(eventWrapper.Data, eventWrapper.Properties); - var @event = jObject.ToObject(); if (@event != null) - return Handle(@event); + return Handle(@event, properties); break; } case string eventDataJson: - return Handle(eventDataJson.JsonToObject()); + return Handle(eventDataJson.JsonToObject(), properties); } throw new ArgumentException(@$"Unsupported event DataType:{eventData.GetType()}", nameof(eventData)); - - - } } diff --git a/src/WeihanLi.Common/Event/EventProperties.cs b/src/WeihanLi.Common/Event/EventProperties.cs index d1452d8a..33dfc768 100644 --- a/src/WeihanLi.Common/Event/EventProperties.cs +++ b/src/WeihanLi.Common/Event/EventProperties.cs @@ -5,6 +5,7 @@ namespace WeihanLi.Common.Event; public sealed class EventProperties: Dictionary, IEventBase { - public DateTimeOffset EventAt { get; init; } - public string EventId { get; init; } + public DateTimeOffset EventAt { get; set; } + public string? EventId { get; set; } + public string? TraceId { get; set; } } diff --git a/src/WeihanLi.Common/Event/EventQueueInMemory.cs b/src/WeihanLi.Common/Event/EventQueueInMemory.cs index 89bc5ced..032a4fd8 100644 --- a/src/WeihanLi.Common/Event/EventQueueInMemory.cs +++ b/src/WeihanLi.Common/Event/EventQueueInMemory.cs @@ -2,46 +2,48 @@ // Licensed under the Apache license. using System.Collections.Concurrent; +using System.Diagnostics; namespace WeihanLi.Common.Event; public sealed class EventQueueInMemory : IEventQueue { - private readonly ConcurrentDictionary> _eventQueues = new(); + private readonly ConcurrentDictionary> _eventQueues = new(); public ICollection GetQueues() => _eventQueues.Keys; public Task> GetQueuesAsync() => Task.FromResult(GetQueues()); - public bool Enqueue(string queueName, TEvent @event) where TEvent : class + public bool Enqueue(string queueName, TEvent @event, EventProperties? properties = null) where TEvent : class { - var internalEvent = @event switch + properties ??= new(); + if (string.IsNullOrEmpty(properties.EventId)) { - IEventBase eventBase => new EventWrapper() - { - Data = @event, - Properties = new EventProperties - { - EventId = eventBase.EventId, - EventAt = eventBase.EventAt - } - }, - _ => new EventWrapper() - { - Data = @event, - Properties = new EventProperties - { - EventId = Guid.NewGuid().ToString(), - EventAt = DateTimeOffset.UtcNow - } - } + properties.EventId = Guid.NewGuid().ToString(); + } + if (properties.EventAt == default) + { + properties.EventAt = DateTimeOffset.Now; + } + if (string.IsNullOrEmpty(properties.TraceId) && Activity.Current != null) + { + properties.TraceId = Activity.Current.TraceId.ToString(); + } + var internalEvent = new EventWrapper + { + Data = @event, + Properties = properties }; - var queue = _eventQueues.GetOrAdd(queueName, _ => new ConcurrentQueue()); + var queue = _eventQueues.GetOrAdd(queueName, _ => new ConcurrentQueue()); queue.Enqueue(internalEvent); return true; } - public Task EnqueueAsync(string queueName, TEvent @event) where TEvent : class => Task.FromResult(Enqueue(queueName, @event)); + public Task EnqueueAsync(string queueName, TEvent @event, EventProperties? properties = null) where TEvent : class => Task.FromResult(Enqueue(queueName, @event, properties)); + public Task TryDequeueAsync(string queueName, out object @event, out EventProperties properties) + { + throw new NotImplementedException(); + } public IEventBase? Dequeue(string queueName) { @@ -54,11 +56,6 @@ public bool Enqueue(string queueName, TEvent @event) where TEvent : clas return null; } - public Task DequeueAsync(string queueName) - { - return Task.FromResult(Dequeue(queueName)); - } - public bool TryRemoveQueue(string queueName) { return _eventQueues.TryRemove(queueName, out _); diff --git a/src/WeihanLi.Common/Event/EventQueuePublisher.cs b/src/WeihanLi.Common/Event/EventQueuePublisher.cs index fd91aeb1..e06787b1 100644 --- a/src/WeihanLi.Common/Event/EventQueuePublisher.cs +++ b/src/WeihanLi.Common/Event/EventQueuePublisher.cs @@ -2,20 +2,36 @@ // Licensed under the Apache license. using Microsoft.Extensions.Options; +using System.Diagnostics; +using WeihanLi.Common.Helpers; namespace WeihanLi.Common.Event; public class EventQueuePublisher(IEventQueue eventQueue, IOptions options) : IEventPublisher { private readonly IEventQueue _eventQueue = eventQueue; - private readonly EventQueuePublisherOptions _options = options.Value; - public virtual Task PublishAsync(TEvent @event) + public virtual Task PublishAsync(TEvent @event, EventProperties? properties) where TEvent : class { + properties ??= new(); + if (string.IsNullOrEmpty(properties.EventId)) + { + properties.EventId = Guid.NewGuid().ToString(); + } + if (properties.EventAt == default) + { + properties.EventAt = DateTimeOffset.Now; + } + using var activity = DiagnosticHelper.ActivitySource.StartActivity(); + if (string.IsNullOrEmpty(properties.TraceId) && Activity.Current != null) + { + properties.TraceId = Activity.Current.TraceId.ToString(); + } + var queueName = _options.EventQueueNameResolver.Invoke(@event.GetType()) ?? "events"; - return _eventQueue.EnqueueAsync(queueName, @event); + return _eventQueue.EnqueueAsync(queueName, @event, properties); } } diff --git a/src/WeihanLi.Common/Event/IEventPublisher.cs b/src/WeihanLi.Common/Event/IEventPublisher.cs index 52710f21..d08c33e7 100644 --- a/src/WeihanLi.Common/Event/IEventPublisher.cs +++ b/src/WeihanLi.Common/Event/IEventPublisher.cs @@ -10,6 +10,7 @@ public interface IEventPublisher /// /// event type /// event data + /// properties /// whether the operation succeed - Task PublishAsync(TEvent @event) where TEvent : class; + Task PublishAsync(TEvent @event, EventProperties? properties = null) where TEvent : class; } diff --git a/src/WeihanLi.Common/Event/IEventQueue.cs b/src/WeihanLi.Common/Event/IEventQueue.cs index 5cd1b70c..81b52895 100644 --- a/src/WeihanLi.Common/Event/IEventQueue.cs +++ b/src/WeihanLi.Common/Event/IEventQueue.cs @@ -1,30 +1,27 @@ // Copyright (c) Weihan Li. All rights reserved. // Licensed under the Apache license. +using System.Diagnostics.CodeAnalysis; + namespace WeihanLi.Common.Event; public interface IEventQueue { Task> GetQueuesAsync(); - Task EnqueueAsync(string queueName, TEvent @event) + Task EnqueueAsync(string queueName, TEvent @event, EventProperties? properties = null) where TEvent : class; - Task DequeueAsync(string queueName); + Task TryDequeueAsync(string queueName, [MaybeNullWhen(false)]out object @event, [MaybeNullWhen(false)]out EventProperties properties); } public static class EventQueueExtensions { private const string DefaultQueueName = "events"; - public static Task EnqueueAsync(this IEventQueue eventQueue, TEvent @event) + public static Task EnqueueAsync(this IEventQueue eventQueue, TEvent @event, EventProperties? properties = null) where TEvent : class { return eventQueue.EnqueueAsync(DefaultQueueName, @event); } - - public static Task DequeueAsync(this IEventQueue eventQueue) - { - return eventQueue.DequeueAsync(DefaultQueueName); - } } diff --git a/src/WeihanLi.Common/Extensions/TaskExtension.cs b/src/WeihanLi.Common/Extensions/TaskExtension.cs index 0fe4fde0..c4a1a65d 100644 --- a/src/WeihanLi.Common/Extensions/TaskExtension.cs +++ b/src/WeihanLi.Common/Extensions/TaskExtension.cs @@ -28,6 +28,9 @@ public static Task AsTask(this CancellationToken cancellationToken) public static Task WhenAllSafely(this IEnumerable tasks, Action? onException = null) => Task.WhenAll(tasks.Select(async t => { +#if NET8_0_OR_GREATER + await t.ConfigureAwait(ConfigureAwaitOptions.SuppressThrowing); +#else try { await t; @@ -36,6 +39,7 @@ public static Task WhenAllSafely(this IEnumerable tasks, Action { onException?.Invoke(ex); } +#endif })); public static Task WhenAll(this IEnumerable> tasks) => Task.WhenAll(tasks); diff --git a/test/WeihanLi.Common.Test/AspectTest/ProxyFactoryTest.cs b/test/WeihanLi.Common.Test/AspectTest/ProxyFactoryTest.cs index a8f0c826..f821ce64 100644 --- a/test/WeihanLi.Common.Test/AspectTest/ProxyFactoryTest.cs +++ b/test/WeihanLi.Common.Test/AspectTest/ProxyFactoryTest.cs @@ -105,7 +105,7 @@ public void CreateProxyInstanceOfAbstract() var eventHandlerProxy = _proxyFactory.CreateProxy>(); Assert.NotNull(eventHandlerProxy); Assert.True(eventHandlerProxy.GetType().Namespace?.StartsWith(NamespacePrefix)); - eventHandlerProxy.Handle(new TestEvent()); + eventHandlerProxy.Handle(new TestEvent(), new()); } [Fact] @@ -152,6 +152,6 @@ public void GenericTypeTest() var eventHandlerProxy = _proxyFactory.CreateProxy>(); Assert.NotNull(eventHandlerProxy); Assert.True(eventHandlerProxy.GetType().Namespace?.StartsWith(NamespacePrefix)); - eventHandlerProxy.Handle(new TestEvent()); + eventHandlerProxy.Handle(new TestEvent(), new()); } } diff --git a/test/WeihanLi.Common.Test/AspectTest/ServiceCollectionBuildTest.cs b/test/WeihanLi.Common.Test/AspectTest/ServiceCollectionBuildTest.cs index 7b1b59b1..cb51aad4 100644 --- a/test/WeihanLi.Common.Test/AspectTest/ServiceCollectionBuildTest.cs +++ b/test/WeihanLi.Common.Test/AspectTest/ServiceCollectionBuildTest.cs @@ -97,7 +97,7 @@ public async Task ClassTest() Assert.True(eventHandlerType.IsSealed); Assert.True(eventHandlerType.Assembly.IsDynamic); - var handTask = eventHandler.Handle(new TestEvent()); + var handTask = eventHandler.Handle(new TestEvent(), new()); Assert.NotNull(handTask); await handTask; } diff --git a/test/WeihanLi.Common.Test/AspectTest/ServiceContainerBuilderBuildTest.cs b/test/WeihanLi.Common.Test/AspectTest/ServiceContainerBuilderBuildTest.cs index 5b03dc75..b15995aa 100644 --- a/test/WeihanLi.Common.Test/AspectTest/ServiceContainerBuilderBuildTest.cs +++ b/test/WeihanLi.Common.Test/AspectTest/ServiceContainerBuilderBuildTest.cs @@ -94,7 +94,7 @@ public async Task ClassTest() Assert.True(eventHandlerType.IsSealed); Assert.True(eventHandlerType.Assembly.IsDynamic); - var handTask = eventHandler.Handle(new TestEvent()); + var handTask = eventHandler.Handle(new TestEvent(), new()); Assert.NotNull(handTask); await handTask; } From f609d29ebb413a307351bbd500eb9ec497bd2903 Mon Sep 17 00:00:00 2001 From: Weihan Li Date: Fri, 8 Mar 2024 00:10:50 +0800 Subject: [PATCH 09/10] refactor: refactor events ++ --- .../Event/DelegateEventHandler.cs | 36 ++++++++---- src/WeihanLi.Common/Event/EventBase.cs | 5 +- src/WeihanLi.Common/Event/EventBus.cs | 3 +- src/WeihanLi.Common/Event/EventHandler.cs | 16 +++--- .../Event/EventHandlerFactory.cs | 5 +- src/WeihanLi.Common/Event/EventProperties.cs | 2 +- .../Event/EventQueueInMemory.cs | 24 ++++---- .../Event/EventQueuePublisher.cs | 3 +- .../Event/EventStoreInMemory.cs | 2 +- .../Event/EventSubscriptionManager.cs | 33 +++++------ .../Event/IEventHandlerFactory.cs | 1 - src/WeihanLi.Common/Event/IEventPublisher.cs | 2 +- src/WeihanLi.Common/Event/IEventQueue.cs | 3 +- src/WeihanLi.Common/Event/IEventSubscriber.cs | 57 +++++++++++++------ .../AspectTest/ServiceCollectionBuildTest.cs | 2 +- .../ServiceContainerBuilderBuildTest.cs | 2 +- 16 files changed, 112 insertions(+), 84 deletions(-) diff --git a/src/WeihanLi.Common/Event/DelegateEventHandler.cs b/src/WeihanLi.Common/Event/DelegateEventHandler.cs index 37970520..c0952346 100644 --- a/src/WeihanLi.Common/Event/DelegateEventHandler.cs +++ b/src/WeihanLi.Common/Event/DelegateEventHandler.cs @@ -5,31 +5,43 @@ namespace WeihanLi.Common.Event; -public static class DelegateEventHandler -{ - public static DelegateEventHandler FromAction(Action action) where TEvent : class => new(action); - - public static DelegateEventHandler FromFunc(Func func) where TEvent : class => new(func); -} - public sealed class DelegateEventHandler : EventHandlerBase - where TEvent : class { - private readonly Func _func; + private readonly Func _func; public DelegateEventHandler(Action action) { Guard.NotNull(action); - _func = action.WrapTask(); + _func = (e, _) => + { + action(e); + return Task.CompletedTask; + }; + } + + public DelegateEventHandler(Action action) + { + Guard.NotNull(action); + _func = (e, properties) => + { + action(e, properties); + return Task.CompletedTask; + }; } public DelegateEventHandler(Func func) + { + Guard.NotNull(func); + _func = (e, _) => func(e); + } + + public DelegateEventHandler(Func func) { _func = Guard.NotNull(func); } - public override Task Handle(TEvent @event, EventProperties eventProperties) + public override Task Handle(TEvent @event, EventProperties properties) { - return _func.Invoke(@event); + return _func.Invoke(@event, properties); } } diff --git a/src/WeihanLi.Common/Event/EventBase.cs b/src/WeihanLi.Common/Event/EventBase.cs index 7c31f11f..f76790a9 100644 --- a/src/WeihanLi.Common/Event/EventBase.cs +++ b/src/WeihanLi.Common/Event/EventBase.cs @@ -52,8 +52,9 @@ protected EventBase(string eventId, DateTimeOffset eventAt) } } -internal interface IEventWrapper : IEventBase +internal interface IEventWrapper { + EventProperties Properties { get; } object Data { get; } } @@ -62,8 +63,6 @@ internal sealed class EventWrapper : IEventWrapper public required T Data { get; init; } object IEventWrapper.Data => Data!; public required EventProperties Properties { get; init; } - public DateTimeOffset EventAt => Properties.EventAt; - public string EventId => Properties.EventId!; } public static class EventBaseExtensions diff --git a/src/WeihanLi.Common/Event/EventBus.cs b/src/WeihanLi.Common/Event/EventBus.cs index 747d110d..ac542331 100644 --- a/src/WeihanLi.Common/Event/EventBus.cs +++ b/src/WeihanLi.Common/Event/EventBus.cs @@ -18,7 +18,7 @@ public sealed class EventBus(IEventSubscriptionManager subscriptionManager, IEve private readonly IEventSubscriptionManager _subscriptionManager = subscriptionManager; private readonly IEventHandlerFactory _eventHandlerFactory = eventHandlerFactory; - public async Task PublishAsync(TEvent @event, EventProperties? properties) where TEvent : class + public async Task PublishAsync(TEvent @event, EventProperties? properties) { properties ??= new(); if (string.IsNullOrEmpty(properties.EventId)) @@ -56,6 +56,7 @@ public async Task PublishAsync(TEvent @event, EventProperties? pro public bool Subscribe(Type eventType, Type eventHandlerType) => _subscriptionManager.Subscribe(eventType, eventHandlerType); public Task SubscribeAsync(Type eventType, Type eventHandlerType) => _subscriptionManager.SubscribeAsync(eventType, eventHandlerType); + public Task SubscribeAsync(IEventHandler eventHandler) => _subscriptionManager.SubscribeAsync(eventHandler); public bool UnSubscribe(Type eventType, Type eventHandlerType) => _subscriptionManager.UnSubscribe(eventType, eventHandlerType); diff --git a/src/WeihanLi.Common/Event/EventHandler.cs b/src/WeihanLi.Common/Event/EventHandler.cs index 5d77cd4f..d832c43a 100644 --- a/src/WeihanLi.Common/Event/EventHandler.cs +++ b/src/WeihanLi.Common/Event/EventHandler.cs @@ -11,7 +11,7 @@ public interface IEventHandler Task Handle(object eventData, EventProperties properties); } -public interface IEventHandler : IEventHandler where TEvent : class +public interface IEventHandler : IEventHandler { /// /// Handler event @@ -21,7 +21,7 @@ public interface IEventHandler : IEventHandler where TEvent : class Task Handle(TEvent @event, EventProperties properties); } -public abstract class EventHandlerBase : IEventHandler where TEvent : class +public abstract class EventHandlerBase : IEventHandler { public abstract Task Handle(TEvent @event, EventProperties eventProperties); @@ -35,13 +35,11 @@ public virtual Task Handle(object eventData, EventProperties properties) return Handle(data, properties); case JObject jObject: - { - var @event = jObject.ToObject(); - if (@event != null) - return Handle(@event, properties); - - break; - } + var @event = jObject.ToObject(); + if (@event != null) + return Handle(@event, properties); + break; + case string eventDataJson: return Handle(eventDataJson.JsonToObject(), properties); } diff --git a/src/WeihanLi.Common/Event/EventHandlerFactory.cs b/src/WeihanLi.Common/Event/EventHandlerFactory.cs index 32ee872d..bb685d4e 100644 --- a/src/WeihanLi.Common/Event/EventHandlerFactory.cs +++ b/src/WeihanLi.Common/Event/EventHandlerFactory.cs @@ -18,10 +18,7 @@ public ICollection GetHandlers(Type eventType) { var eventHandlers = _eventHandlers.GetOrAdd(eventType, type => { - var handlerTypes = _subscriptionManager.GetEventHandlerTypes(type); - var handlers = handlerTypes - .Select(t => (IEventHandler)_serviceProvider.GetServiceOrCreateInstance(t)) - .ToArray(); + var handlers = _subscriptionManager.GetEventHandlers(type); return handlers; }); return eventHandlers; diff --git a/src/WeihanLi.Common/Event/EventProperties.cs b/src/WeihanLi.Common/Event/EventProperties.cs index 33dfc768..4c36de44 100644 --- a/src/WeihanLi.Common/Event/EventProperties.cs +++ b/src/WeihanLi.Common/Event/EventProperties.cs @@ -6,6 +6,6 @@ namespace WeihanLi.Common.Event; public sealed class EventProperties: Dictionary, IEventBase { public DateTimeOffset EventAt { get; set; } - public string? EventId { get; set; } + public string EventId { get; set; } = Guid.NewGuid().ToString(); public string? TraceId { get; set; } } diff --git a/src/WeihanLi.Common/Event/EventQueueInMemory.cs b/src/WeihanLi.Common/Event/EventQueueInMemory.cs index 032a4fd8..7236c8d6 100644 --- a/src/WeihanLi.Common/Event/EventQueueInMemory.cs +++ b/src/WeihanLi.Common/Event/EventQueueInMemory.cs @@ -3,6 +3,7 @@ using System.Collections.Concurrent; using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; namespace WeihanLi.Common.Event; @@ -14,7 +15,7 @@ public sealed class EventQueueInMemory : IEventQueue public Task> GetQueuesAsync() => Task.FromResult(GetQueues()); - public bool Enqueue(string queueName, TEvent @event, EventProperties? properties = null) where TEvent : class + public bool Enqueue(string queueName, TEvent @event, EventProperties? properties = null) { properties ??= new(); if (string.IsNullOrEmpty(properties.EventId)) @@ -39,21 +40,24 @@ public bool Enqueue(string queueName, TEvent @event, EventProperties? pr return true; } - public Task EnqueueAsync(string queueName, TEvent @event, EventProperties? properties = null) where TEvent : class => Task.FromResult(Enqueue(queueName, @event, properties)); - public Task TryDequeueAsync(string queueName, out object @event, out EventProperties properties) - { - throw new NotImplementedException(); - } + public Task EnqueueAsync(string queueName, TEvent @event, EventProperties? properties = null) => Task.FromResult(Enqueue(queueName, @event, properties)); - public IEventBase? Dequeue(string queueName) + public Task TryDequeueAsync(string queueName, [MaybeNullWhen(false)]out object @event, [MaybeNullWhen(false)]out EventProperties properties) { + @event = default; + properties = default; + if (_eventQueues.TryGetValue(queueName, out var queue)) { - queue.TryDequeue(out var @event); - return @event; + if (queue.TryDequeue(out var eventWrapper)) + { + @event = eventWrapper.Data; + properties = eventWrapper.Properties; + return Task.FromResult(true); + } } - return null; + return Task.FromResult(false); } public bool TryRemoveQueue(string queueName) diff --git a/src/WeihanLi.Common/Event/EventQueuePublisher.cs b/src/WeihanLi.Common/Event/EventQueuePublisher.cs index e06787b1..9dc6d340 100644 --- a/src/WeihanLi.Common/Event/EventQueuePublisher.cs +++ b/src/WeihanLi.Common/Event/EventQueuePublisher.cs @@ -13,8 +13,9 @@ public class EventQueuePublisher(IEventQueue eventQueue, IOptions PublishAsync(TEvent @event, EventProperties? properties) - where TEvent : class { + Guard.NotNull(@event); + properties ??= new(); if (string.IsNullOrEmpty(properties.EventId)) { diff --git a/src/WeihanLi.Common/Event/EventStoreInMemory.cs b/src/WeihanLi.Common/Event/EventStoreInMemory.cs index dfb29c52..a453a2d9 100644 --- a/src/WeihanLi.Common/Event/EventStoreInMemory.cs +++ b/src/WeihanLi.Common/Event/EventStoreInMemory.cs @@ -24,7 +24,7 @@ public int DeleteEvents(ICollection eventIds) { if (eventIds.IsNullOrEmpty()) return 0; - + return eventIds.Count(eventId => _events.TryRemove(eventId, out _)); } diff --git a/src/WeihanLi.Common/Event/EventSubscriptionManager.cs b/src/WeihanLi.Common/Event/EventSubscriptionManager.cs index c9e9253b..6ed09d08 100644 --- a/src/WeihanLi.Common/Event/EventSubscriptionManager.cs +++ b/src/WeihanLi.Common/Event/EventSubscriptionManager.cs @@ -13,17 +13,17 @@ public interface IEventSubscriptionManager : IEventSubscriber /// /// event /// event handlers types - ICollection GetEventHandlerTypes(Type eventType); + ICollection GetEventHandlers(Type eventType); } public sealed class EventSubscriptionManagerInMemory : IEventSubscriptionManager { - private readonly ConcurrentDictionary> _eventHandlers = new(); + private readonly ConcurrentDictionary> _eventHandlers = new(); public bool Subscribe(Type eventType, Type eventHandlerType) { var handlers = _eventHandlers.GetOrAdd(eventType, []); - return handlers.TryAdd(eventHandlerType); + return handlers.TryAdd((IEventHandler)DependencyResolver.Current.GetService(eventHandlerType)); } public Task SubscribeAsync(Type eventType, Type eventHandlerType) @@ -31,11 +31,18 @@ public Task SubscribeAsync(Type eventType, Type eventHandlerType) return Task.FromResult(Subscribe(eventType, eventHandlerType)); } + public Task SubscribeAsync(IEventHandler eventHandler) + { + var handlers = _eventHandlers.GetOrAdd(typeof(TEvent), []); + return Task.FromResult(handlers.TryAdd(eventHandler)); + } + public bool UnSubscribe(Type eventType, Type eventHandlerType) { if (_eventHandlers.TryGetValue(eventType, out var handlers)) { - return handlers.TryRemove(eventHandlerType); + var handler = handlers.FirstOrDefault(h => h.GetType() == eventHandlerType); + return handler is not null && handlers.TryRemove(handler); } return false; @@ -46,7 +53,7 @@ public Task UnSubscribeAsync(Type eventType, Type eventHandlerType) return Task.FromResult(UnSubscribe(eventType, eventHandlerType)); } - public ICollection GetEventHandlerTypes(Type eventType) + public ICollection GetEventHandlers(Type eventType) { return _eventHandlers[eventType]; } @@ -56,22 +63,10 @@ public sealed class NullEventSubscriptionManager : IEventSubscriptionManager { public static readonly IEventSubscriptionManager Instance = new NullEventSubscriptionManager(); - public bool Subscribe(Type eventType, Type eventHandlerType) => false; - public Task SubscribeAsync(Type eventType, Type eventHandlerType) => Task.FromResult(false); - - public bool UnSubscribe(Type eventType, Type eventHandlerType) => false; + public Task SubscribeAsync(IEventHandler eventHandler) => Task.FromResult(false); public Task UnSubscribeAsync(Type eventType, Type eventHandlerType) => Task.FromResult(false); - public ICollection GetEventHandlerTypes(Type eventType) => Array.Empty(); -} - -public static class EventSubscriptionManagerExtensions -{ - public static ICollection GetEventHandlerTypes(this IEventSubscriptionManager subscriptionManager) - where TEvent : class, IEventBase - { - return subscriptionManager.GetEventHandlerTypes(typeof(TEvent)); - } + public ICollection GetEventHandlers(Type eventType) => Array.Empty(); } diff --git a/src/WeihanLi.Common/Event/IEventHandlerFactory.cs b/src/WeihanLi.Common/Event/IEventHandlerFactory.cs index 5784ddbc..cae44728 100644 --- a/src/WeihanLi.Common/Event/IEventHandlerFactory.cs +++ b/src/WeihanLi.Common/Event/IEventHandlerFactory.cs @@ -11,7 +11,6 @@ public interface IEventHandlerFactory public static class EventHandlerFactoryExtensions { public static ICollection> GetHandlers(this IEventHandlerFactory eventHandlerFactory) - where TEvent : class { return eventHandlerFactory.GetHandlers(typeof(TEvent)) .Cast>() diff --git a/src/WeihanLi.Common/Event/IEventPublisher.cs b/src/WeihanLi.Common/Event/IEventPublisher.cs index d08c33e7..6da1c5bb 100644 --- a/src/WeihanLi.Common/Event/IEventPublisher.cs +++ b/src/WeihanLi.Common/Event/IEventPublisher.cs @@ -12,5 +12,5 @@ public interface IEventPublisher /// event data /// properties /// whether the operation succeed - Task PublishAsync(TEvent @event, EventProperties? properties = null) where TEvent : class; + Task PublishAsync(TEvent @event, EventProperties? properties = null); } diff --git a/src/WeihanLi.Common/Event/IEventQueue.cs b/src/WeihanLi.Common/Event/IEventQueue.cs index 81b52895..5677c2db 100644 --- a/src/WeihanLi.Common/Event/IEventQueue.cs +++ b/src/WeihanLi.Common/Event/IEventQueue.cs @@ -9,8 +9,7 @@ public interface IEventQueue { Task> GetQueuesAsync(); - Task EnqueueAsync(string queueName, TEvent @event, EventProperties? properties = null) - where TEvent : class; + Task EnqueueAsync(string queueName, TEvent @event, EventProperties? properties = null); Task TryDequeueAsync(string queueName, [MaybeNullWhen(false)]out object @event, [MaybeNullWhen(false)]out EventProperties properties); } diff --git a/src/WeihanLi.Common/Event/IEventSubscriber.cs b/src/WeihanLi.Common/Event/IEventSubscriber.cs index a92347f5..f9e1da05 100644 --- a/src/WeihanLi.Common/Event/IEventSubscriber.cs +++ b/src/WeihanLi.Common/Event/IEventSubscriber.cs @@ -5,14 +5,6 @@ namespace WeihanLi.Common.Event; public interface IEventSubscriber { - /// - /// add event handler for event - /// - /// event type - /// eventHandler type - /// whether the operation success - bool Subscribe(Type eventType, Type eventHandlerType); - /// /// add event handler for event /// @@ -22,12 +14,12 @@ public interface IEventSubscriber Task SubscribeAsync(Type eventType, Type eventHandlerType); /// - /// remove event handler for event + /// add event handler instance for event /// - /// event type - /// eventHandler type - /// whether the operation success - bool UnSubscribe(Type eventType, Type eventHandlerType); + /// event handler + /// event type + /// + Task SubscribeAsync(IEventHandler eventHandler); /// /// remove event handler for event @@ -40,6 +32,17 @@ public interface IEventSubscriber public static class EventSubscriberExtensions { + /// + /// add event handler for event + /// + /// TEvent + /// whether the operation success + public static bool Subscribe(this IEventSubscriber subscriber, Func handler) + { + return subscriber.SubscribeAsync(new DelegateEventHandler(handler)) + .GetAwaiter().GetResult(); + } + /// /// add event handler for event /// @@ -48,11 +51,22 @@ public static class EventSubscriberExtensions /// whether the operation success public static bool Subscribe(this IEventSubscriber subscriber) where TEventHandler : class, IEventHandler - where TEvent : class { return subscriber.Subscribe(typeof(TEvent), typeof(TEventHandler)); } + /// + /// add event handler for event + /// + /// event subscriber + /// event type + /// eventHandler type + /// whether the operation success + public static bool Subscribe(this IEventSubscriber subscriber, Type eventType, Type eventHandlerType) + { + return subscriber.SubscribeAsync(eventType, eventHandlerType).GetAwaiter().GetResult(); + } + /// /// add event handler for event /// @@ -61,7 +75,6 @@ public static bool Subscribe(this IEventSubscriber subscr /// whether the operation success public static Task SubscribeAsync(this IEventSubscriber subscriber) where TEventHandler : class, IEventHandler - where TEvent : class, IEventBase { return subscriber.SubscribeAsync(typeof(TEvent), typeof(TEventHandler)); } @@ -74,11 +87,22 @@ public static Task SubscribeAsync(this IEventSubscr /// whether the operation success public static bool UnSubscribe(this IEventSubscriber subscriber) where TEventHandler : class, IEventHandler - where TEvent : class, IEventBase { return subscriber.UnSubscribe(typeof(TEvent), typeof(TEventHandler)); } + /// + /// remove event handler for event + /// + /// event subscriber + /// event type + /// eventHandler type + /// whether the operation success + public static bool UnSubscribe(this IEventSubscriber subscriber, Type eventType, Type eventHandlerType) + { + return subscriber.UnSubscribeAsync(eventType, eventHandlerType).GetAwaiter().GetResult(); + } + /// /// remove event handler for event /// @@ -87,7 +111,6 @@ public static bool UnSubscribe(this IEventSubscriber subs /// whether the operation success public static Task UnSubscribeAsync(this IEventSubscriber subscriber) where TEventHandler : class, IEventHandler - where TEvent : class, IEventBase { return subscriber.UnSubscribeAsync(typeof(TEvent), typeof(TEventHandler)); } diff --git a/test/WeihanLi.Common.Test/AspectTest/ServiceCollectionBuildTest.cs b/test/WeihanLi.Common.Test/AspectTest/ServiceCollectionBuildTest.cs index cb51aad4..993f2a02 100644 --- a/test/WeihanLi.Common.Test/AspectTest/ServiceCollectionBuildTest.cs +++ b/test/WeihanLi.Common.Test/AspectTest/ServiceCollectionBuildTest.cs @@ -29,7 +29,7 @@ public ServiceCollectionBuildTest(ITestOutputHelper output) services.AddSingleton(); services.AddOptions(); - services.AddSingleton>(DelegateEventHandler.FromAction(_ => { })); + services.AddSingleton>(new DelegateEventHandler(_ => { })); services.AddSingleton(typeof(IEventHandler<>), typeof(TestGenericEventHandler<>)); diff --git a/test/WeihanLi.Common.Test/AspectTest/ServiceContainerBuilderBuildTest.cs b/test/WeihanLi.Common.Test/AspectTest/ServiceContainerBuilderBuildTest.cs index b15995aa..8cfe4028 100644 --- a/test/WeihanLi.Common.Test/AspectTest/ServiceContainerBuilderBuildTest.cs +++ b/test/WeihanLi.Common.Test/AspectTest/ServiceContainerBuilderBuildTest.cs @@ -26,7 +26,7 @@ public ServiceContainerBuilderBuildTest(ITestOutputHelper output) new OptionsWrapper(new EventQueuePublisherOptions())); services.AddSingleton(); - services.AddSingleton>(DelegateEventHandler.FromAction(_ => { })); + services.AddSingleton>(new DelegateEventHandler(_ => { })); services.AddSingleton(typeof(IEventHandler<>), typeof(ServiceCollectionBuildTest.TestGenericEventHandler<>)); From 1d1dfc01ae4014e973b3bf60025b906b8deaf53e Mon Sep 17 00:00:00 2001 From: Weihan Li Date: Fri, 8 Mar 2024 00:14:30 +0800 Subject: [PATCH 10/10] refactor: events cleanup --- src/WeihanLi.Common/Event/EventBusExtensions.cs | 3 --- src/WeihanLi.Common/Event/EventHandlerFactory.cs | 12 ++---------- 2 files changed, 2 insertions(+), 13 deletions(-) diff --git a/src/WeihanLi.Common/Event/EventBusExtensions.cs b/src/WeihanLi.Common/Event/EventBusExtensions.cs index fc840732..b010e520 100644 --- a/src/WeihanLi.Common/Event/EventBusExtensions.cs +++ b/src/WeihanLi.Common/Event/EventBusExtensions.cs @@ -81,7 +81,4 @@ public static IEventBuilder RegisterEventHandlers(this IEventBuilder builder, Fu return builder; } - - public static Task PublishAsync(this IEventPublisher eventPublisher, TEvent @event) where TEvent : class - => eventPublisher.PublishAsync(@event, null); } diff --git a/src/WeihanLi.Common/Event/EventHandlerFactory.cs b/src/WeihanLi.Common/Event/EventHandlerFactory.cs index bb685d4e..e010ba7a 100644 --- a/src/WeihanLi.Common/Event/EventHandlerFactory.cs +++ b/src/WeihanLi.Common/Event/EventHandlerFactory.cs @@ -1,26 +1,18 @@ // Copyright (c) Weihan Li. All rights reserved. // Licensed under the Apache license. -using System.Collections.Concurrent; using System.Diagnostics.CodeAnalysis; -using WeihanLi.Common.Helpers; namespace WeihanLi.Common.Event; -public sealed class DefaultEventHandlerFactory(IEventSubscriptionManager subscriptionManager, IServiceProvider serviceProvider) : IEventHandlerFactory +public sealed class DefaultEventHandlerFactory(IEventSubscriptionManager subscriptionManager) : IEventHandlerFactory { private readonly IEventSubscriptionManager _subscriptionManager = subscriptionManager; - private readonly ConcurrentDictionary> _eventHandlers = new(); - private readonly IServiceProvider _serviceProvider = serviceProvider; [RequiresUnreferencedCode("Unreferenced code may be used")] public ICollection GetHandlers(Type eventType) { - var eventHandlers = _eventHandlers.GetOrAdd(eventType, type => - { - var handlers = _subscriptionManager.GetEventHandlers(type); - return handlers; - }); + var eventHandlers = _subscriptionManager.GetEventHandlers(eventType); return eventHandlers; } }