diff --git a/GFramework.Cqrs.Tests/Cqrs/AlphaDeterministicNotificationHandler.cs b/GFramework.Cqrs.Tests/Cqrs/AlphaDeterministicNotificationHandler.cs
new file mode 100644
index 00000000..5142d5b7
--- /dev/null
+++ b/GFramework.Cqrs.Tests/Cqrs/AlphaDeterministicNotificationHandler.cs
@@ -0,0 +1,23 @@
+using System.Threading;
+using System.Threading.Tasks;
+using GFramework.Cqrs.Abstractions.Cqrs;
+
+namespace GFramework.Cqrs.Tests.Cqrs;
+
+///
+/// 名称排序上应先于 Zeta 处理器执行的通知处理器。
+///
+internal sealed class AlphaDeterministicNotificationHandler : INotificationHandler
+{
+ ///
+ /// 记录当前处理器已执行。
+ ///
+ /// 通知实例。
+ /// 取消令牌。
+ /// 已完成任务。
+ public ValueTask Handle(DeterministicOrderNotification notification, CancellationToken cancellationToken)
+ {
+ DeterministicNotificationHandlerState.InvocationOrder.Add(nameof(AlphaDeterministicNotificationHandler));
+ return ValueTask.CompletedTask;
+ }
+}
diff --git a/GFramework.Cqrs.Tests/Cqrs/CapturingLoggerFactoryProvider.cs b/GFramework.Cqrs.Tests/Cqrs/CapturingLoggerFactoryProvider.cs
new file mode 100644
index 00000000..00f3df65
--- /dev/null
+++ b/GFramework.Cqrs.Tests/Cqrs/CapturingLoggerFactoryProvider.cs
@@ -0,0 +1,49 @@
+using System.Collections.Generic;
+using GFramework.Core.Abstractions.Logging;
+using GFramework.Core.Logging;
+using GFramework.Cqrs.Tests.Logging;
+
+namespace GFramework.Cqrs.Tests.Cqrs;
+
+///
+/// 为 CQRS 注册测试捕获真实启动路径中创建的日志记录器。
+///
+///
+/// 处理器注册入口会分别为测试运行时、容器和注册器创建日志器。
+/// 该提供程序统一保留这些测试日志器,以便断言警告是否经由公开入口真正发出。
+///
+internal sealed class CapturingLoggerFactoryProvider : ILoggerFactoryProvider
+{
+ private readonly List _loggers = [];
+
+ ///
+ /// 使用指定的最小日志级别初始化一个新的捕获型日志工厂提供程序。
+ ///
+ /// 要应用到新建测试日志器的最小日志级别。
+ public CapturingLoggerFactoryProvider(LogLevel minLevel = LogLevel.Info)
+ {
+ MinLevel = minLevel;
+ }
+
+ ///
+ /// 获取通过当前提供程序创建的全部测试日志器。
+ ///
+ public IReadOnlyList Loggers => _loggers;
+
+ ///
+ /// 获取或设置新建测试日志器的最小日志级别。
+ ///
+ public LogLevel MinLevel { get; set; }
+
+ ///
+ /// 创建一个测试日志器并将其纳入捕获集合。
+ ///
+ /// 日志记录器名称。
+ /// 用于后续断言的测试日志器。
+ public ILogger CreateLogger(string name)
+ {
+ var logger = new TestLogger(name, MinLevel);
+ _loggers.Add(logger);
+ return logger;
+ }
+}
diff --git a/GFramework.Cqrs.Tests/Cqrs/CqrsHandlerRegistrarTests.cs b/GFramework.Cqrs.Tests/Cqrs/CqrsHandlerRegistrarTests.cs
index dcbfbd2a..76a2b922 100644
--- a/GFramework.Cqrs.Tests/Cqrs/CqrsHandlerRegistrarTests.cs
+++ b/GFramework.Cqrs.Tests/Cqrs/CqrsHandlerRegistrarTests.cs
@@ -614,230 +614,3 @@ internal sealed class CqrsHandlerRegistrarTests
.GetType("GFramework.Cqrs.Internal.CqrsHandlerRegistrar", throwOnError: true)!;
}
}
-
-///
-/// 记录确定性通知处理器的实际执行顺序。
-///
-internal static class DeterministicNotificationHandlerState
-{
- ///
- /// 获取当前测试中的通知处理器执行顺序。
- ///
- public static List InvocationOrder { get; } = [];
-
- ///
- /// 重置共享的执行顺序状态。
- ///
- public static void Reset()
- {
- InvocationOrder.Clear();
- }
-}
-
-///
-/// 用于验证同一通知的多个处理器是否按稳定顺序执行。
-///
-internal sealed record DeterministicOrderNotification : INotification;
-
-///
-/// 故意放在 Alpha 之前声明,用于验证注册器不会依赖源码声明顺序。
-///
-internal sealed class ZetaDeterministicNotificationHandler : INotificationHandler
-{
- ///
- /// 记录当前处理器已执行。
- ///
- /// 通知实例。
- /// 取消令牌。
- /// 已完成任务。
- public ValueTask Handle(DeterministicOrderNotification notification, CancellationToken cancellationToken)
- {
- DeterministicNotificationHandlerState.InvocationOrder.Add(nameof(ZetaDeterministicNotificationHandler));
- return ValueTask.CompletedTask;
- }
-}
-
-///
-/// 名称排序上应先于 Zeta 处理器执行的通知处理器。
-///
-internal sealed class AlphaDeterministicNotificationHandler : INotificationHandler
-{
- ///
- /// 记录当前处理器已执行。
- ///
- /// 通知实例。
- /// 取消令牌。
- /// 已完成任务。
- public ValueTask Handle(DeterministicOrderNotification notification, CancellationToken cancellationToken)
- {
- DeterministicNotificationHandlerState.InvocationOrder.Add(nameof(AlphaDeterministicNotificationHandler));
- return ValueTask.CompletedTask;
- }
-}
-
-///
-/// 为 CQRS 注册测试捕获真实启动路径中创建的日志记录器。
-///
-///
-/// 处理器注册入口会分别为测试运行时、容器和注册器创建日志器。
-/// 该提供程序统一保留这些测试日志器,以便断言警告是否经由公开入口真正发出。
-///
-internal sealed class CapturingLoggerFactoryProvider : ILoggerFactoryProvider
-{
- private readonly List _loggers = [];
-
- ///
- /// 使用指定的最小日志级别初始化一个新的捕获型日志工厂提供程序。
- ///
- /// 要应用到新建测试日志器的最小日志级别。
- public CapturingLoggerFactoryProvider(LogLevel minLevel = LogLevel.Info)
- {
- MinLevel = minLevel;
- }
-
- ///
- /// 获取通过当前提供程序创建的全部测试日志器。
- ///
- public IReadOnlyList Loggers => _loggers;
-
- ///
- /// 获取或设置新建测试日志器的最小日志级别。
- ///
- public LogLevel MinLevel { get; set; }
-
- ///
- /// 创建一个测试日志器并将其纳入捕获集合。
- ///
- /// 日志记录器名称。
- /// 用于后续断言的测试日志器。
- public ILogger CreateLogger(string name)
- {
- var logger = new TestLogger(name, MinLevel);
- _loggers.Add(logger);
- return logger;
- }
-}
-
-///
-/// 用于验证生成注册器路径的通知消息。
-///
-internal sealed record GeneratedRegistryNotification : INotification;
-
-///
-/// 由模拟的源码生成注册器显式注册的通知处理器。
-///
-internal sealed class GeneratedRegistryNotificationHandler : INotificationHandler
-{
- ///
- /// 处理生成注册器测试中的通知。
- ///
- /// 通知实例。
- /// 取消令牌。
- /// 已完成任务。
- public ValueTask Handle(GeneratedRegistryNotification notification, CancellationToken cancellationToken)
- {
- return ValueTask.CompletedTask;
- }
-}
-
-///
-/// 模拟源码生成器为某个程序集生成的 CQRS 处理器注册器。
-///
-internal sealed class GeneratedNotificationHandlerRegistry : ICqrsHandlerRegistry
-{
- ///
- /// 将测试通知处理器注册到目标服务集合。
- ///
- /// 承载处理器映射的服务集合。
- /// 用于记录注册诊断的日志器。
- public void Register(IServiceCollection services, ILogger logger)
- {
- ArgumentNullException.ThrowIfNull(services);
- ArgumentNullException.ThrowIfNull(logger);
-
- services.AddTransient(
- typeof(INotificationHandler),
- typeof(GeneratedRegistryNotificationHandler));
- logger.Debug(
- $"Registered CQRS handler {typeof(GeneratedRegistryNotificationHandler).FullName} as {typeof(INotificationHandler).FullName}.");
- }
-}
-
-///
-/// 用于验证“生成注册器 + reflection fallback”组合路径的私有嵌套处理器容器。
-///
-internal sealed class ReflectionFallbackNotificationContainer
-{
- ///
- /// 获取仅能通过反射补扫接入的私有嵌套处理器类型。
- ///
- public static Type ReflectionOnlyHandlerType => typeof(ReflectionOnlyGeneratedRegistryNotificationHandler);
-
- private sealed class ReflectionOnlyGeneratedRegistryNotificationHandler
- : INotificationHandler
- {
- ///
- /// 处理测试通知。
- ///
- /// 通知实例。
- /// 取消令牌。
- /// 已完成任务。
- public ValueTask Handle(GeneratedRegistryNotification notification, CancellationToken cancellationToken)
- {
- return ValueTask.CompletedTask;
- }
- }
-}
-
-///
-/// 模拟局部生成注册器场景中,仅注册“可由生成代码直接引用”的那部分 handlers。
-///
-internal sealed class PartialGeneratedNotificationHandlerRegistry : ICqrsHandlerRegistry
-{
- ///
- /// 将生成路径可见的通知处理器注册到目标服务集合。
- ///
- /// 承载处理器映射的服务集合。
- /// 用于记录注册诊断的日志器。
- public void Register(IServiceCollection services, ILogger logger)
- {
- ArgumentNullException.ThrowIfNull(services);
- ArgumentNullException.ThrowIfNull(logger);
-
- services.AddTransient(
- typeof(INotificationHandler),
- typeof(GeneratedRegistryNotificationHandler));
- logger.Debug(
- $"Registered CQRS handler {typeof(GeneratedRegistryNotificationHandler).FullName} as {typeof(INotificationHandler).FullName}.");
- }
-}
-
-///
-/// 模拟生成注册器使用私有无参构造器的场景,验证运行时仍可通过缓存工厂激活它。
-///
-internal sealed class PrivateConstructorNotificationHandlerRegistry : ICqrsHandlerRegistry
-{
- ///
- /// 初始化一个新的私有生成注册器实例。
- ///
- private PrivateConstructorNotificationHandlerRegistry()
- {
- }
-
- ///
- /// 将测试通知处理器注册到目标服务集合。
- ///
- /// 承载处理器映射的服务集合。
- /// 用于记录注册诊断的日志器。
- public void Register(IServiceCollection services, ILogger logger)
- {
- ArgumentNullException.ThrowIfNull(services);
- ArgumentNullException.ThrowIfNull(logger);
-
- services.AddTransient(
- typeof(INotificationHandler),
- typeof(GeneratedRegistryNotificationHandler));
- logger.Debug(
- $"Registered CQRS handler {typeof(GeneratedRegistryNotificationHandler).FullName} as {typeof(INotificationHandler).FullName}.");
- }
-}
diff --git a/GFramework.Cqrs.Tests/Cqrs/DeterministicNotificationHandlerState.cs b/GFramework.Cqrs.Tests/Cqrs/DeterministicNotificationHandlerState.cs
new file mode 100644
index 00000000..957eda1d
--- /dev/null
+++ b/GFramework.Cqrs.Tests/Cqrs/DeterministicNotificationHandlerState.cs
@@ -0,0 +1,22 @@
+using System.Collections.Generic;
+
+namespace GFramework.Cqrs.Tests.Cqrs;
+
+///
+/// 记录确定性通知处理器的实际执行顺序。
+///
+internal static class DeterministicNotificationHandlerState
+{
+ ///
+ /// 获取当前测试中的通知处理器执行顺序。
+ ///
+ public static List InvocationOrder { get; } = [];
+
+ ///
+ /// 重置共享的执行顺序状态。
+ ///
+ public static void Reset()
+ {
+ InvocationOrder.Clear();
+ }
+}
diff --git a/GFramework.Cqrs.Tests/Cqrs/DeterministicOrderNotification.cs b/GFramework.Cqrs.Tests/Cqrs/DeterministicOrderNotification.cs
new file mode 100644
index 00000000..9bc0e059
--- /dev/null
+++ b/GFramework.Cqrs.Tests/Cqrs/DeterministicOrderNotification.cs
@@ -0,0 +1,8 @@
+using GFramework.Cqrs.Abstractions.Cqrs;
+
+namespace GFramework.Cqrs.Tests.Cqrs;
+
+///
+/// 用于验证同一通知的多个处理器是否按稳定顺序执行。
+///
+internal sealed record DeterministicOrderNotification : INotification;
diff --git a/GFramework.Cqrs.Tests/Cqrs/GeneratedNotificationHandlerRegistry.cs b/GFramework.Cqrs.Tests/Cqrs/GeneratedNotificationHandlerRegistry.cs
new file mode 100644
index 00000000..ab2c344f
--- /dev/null
+++ b/GFramework.Cqrs.Tests/Cqrs/GeneratedNotificationHandlerRegistry.cs
@@ -0,0 +1,30 @@
+using System;
+using GFramework.Core.Abstractions.Logging;
+using GFramework.Core.Ioc;
+using GFramework.Core.Logging;
+using GFramework.Cqrs.Abstractions.Cqrs;
+
+namespace GFramework.Cqrs.Tests.Cqrs;
+
+///
+/// 模拟源码生成器为某个程序集生成的 CQRS 处理器注册器。
+///
+internal sealed class GeneratedNotificationHandlerRegistry : ICqrsHandlerRegistry
+{
+ ///
+ /// 将测试通知处理器注册到目标服务集合。
+ ///
+ /// 承载处理器映射的服务集合。
+ /// 用于记录注册诊断的日志器。
+ public void Register(IServiceCollection services, ILogger logger)
+ {
+ ArgumentNullException.ThrowIfNull(services);
+ ArgumentNullException.ThrowIfNull(logger);
+
+ services.AddTransient(
+ typeof(INotificationHandler),
+ typeof(GeneratedRegistryNotificationHandler));
+ logger.Debug(
+ $"Registered CQRS handler {typeof(GeneratedRegistryNotificationHandler).FullName} as {typeof(INotificationHandler).FullName}.");
+ }
+}
diff --git a/GFramework.Cqrs.Tests/Cqrs/GeneratedRegistryNotification.cs b/GFramework.Cqrs.Tests/Cqrs/GeneratedRegistryNotification.cs
new file mode 100644
index 00000000..98f79991
--- /dev/null
+++ b/GFramework.Cqrs.Tests/Cqrs/GeneratedRegistryNotification.cs
@@ -0,0 +1,8 @@
+using GFramework.Cqrs.Abstractions.Cqrs;
+
+namespace GFramework.Cqrs.Tests.Cqrs;
+
+///
+/// 用于验证生成注册器路径的通知消息。
+///
+internal sealed record GeneratedRegistryNotification : INotification;
diff --git a/GFramework.Cqrs.Tests/Cqrs/GeneratedRegistryNotificationHandler.cs b/GFramework.Cqrs.Tests/Cqrs/GeneratedRegistryNotificationHandler.cs
new file mode 100644
index 00000000..082b16f0
--- /dev/null
+++ b/GFramework.Cqrs.Tests/Cqrs/GeneratedRegistryNotificationHandler.cs
@@ -0,0 +1,22 @@
+using System.Threading;
+using System.Threading.Tasks;
+using GFramework.Cqrs.Abstractions.Cqrs;
+
+namespace GFramework.Cqrs.Tests.Cqrs;
+
+///
+/// 由模拟的源码生成注册器显式注册的通知处理器。
+///
+internal sealed class GeneratedRegistryNotificationHandler : INotificationHandler
+{
+ ///
+ /// 处理生成注册器测试中的通知。
+ ///
+ /// 通知实例。
+ /// 取消令牌。
+ /// 已完成任务。
+ public ValueTask Handle(GeneratedRegistryNotification notification, CancellationToken cancellationToken)
+ {
+ return ValueTask.CompletedTask;
+ }
+}
diff --git a/GFramework.Cqrs.Tests/Cqrs/PartialGeneratedNotificationHandlerRegistry.cs b/GFramework.Cqrs.Tests/Cqrs/PartialGeneratedNotificationHandlerRegistry.cs
new file mode 100644
index 00000000..6bbcfb36
--- /dev/null
+++ b/GFramework.Cqrs.Tests/Cqrs/PartialGeneratedNotificationHandlerRegistry.cs
@@ -0,0 +1,30 @@
+using System;
+using GFramework.Core.Abstractions.Logging;
+using GFramework.Core.Ioc;
+using GFramework.Core.Logging;
+using GFramework.Cqrs.Abstractions.Cqrs;
+
+namespace GFramework.Cqrs.Tests.Cqrs;
+
+///
+/// 模拟局部生成注册器场景中,仅注册“可由生成代码直接引用”的那部分 handlers。
+///
+internal sealed class PartialGeneratedNotificationHandlerRegistry : ICqrsHandlerRegistry
+{
+ ///
+ /// 将生成路径可见的通知处理器注册到目标服务集合。
+ ///
+ /// 承载处理器映射的服务集合。
+ /// 用于记录注册诊断的日志器。
+ public void Register(IServiceCollection services, ILogger logger)
+ {
+ ArgumentNullException.ThrowIfNull(services);
+ ArgumentNullException.ThrowIfNull(logger);
+
+ services.AddTransient(
+ typeof(INotificationHandler),
+ typeof(GeneratedRegistryNotificationHandler));
+ logger.Debug(
+ $"Registered CQRS handler {typeof(GeneratedRegistryNotificationHandler).FullName} as {typeof(INotificationHandler).FullName}.");
+ }
+}
diff --git a/GFramework.Cqrs.Tests/Cqrs/PrivateConstructorNotificationHandlerRegistry.cs b/GFramework.Cqrs.Tests/Cqrs/PrivateConstructorNotificationHandlerRegistry.cs
new file mode 100644
index 00000000..b9bb1b06
--- /dev/null
+++ b/GFramework.Cqrs.Tests/Cqrs/PrivateConstructorNotificationHandlerRegistry.cs
@@ -0,0 +1,37 @@
+using System;
+using GFramework.Core.Abstractions.Logging;
+using GFramework.Core.Ioc;
+using GFramework.Core.Logging;
+using GFramework.Cqrs.Abstractions.Cqrs;
+
+namespace GFramework.Cqrs.Tests.Cqrs;
+
+///
+/// 模拟生成注册器使用私有无参构造器的场景,验证运行时仍可通过缓存工厂激活它。
+///
+internal sealed class PrivateConstructorNotificationHandlerRegistry : ICqrsHandlerRegistry
+{
+ ///
+ /// 初始化一个新的私有生成注册器实例。
+ ///
+ private PrivateConstructorNotificationHandlerRegistry()
+ {
+ }
+
+ ///
+ /// 将测试通知处理器注册到目标服务集合。
+ ///
+ /// 承载处理器映射的服务集合。
+ /// 用于记录注册诊断的日志器。
+ public void Register(IServiceCollection services, ILogger logger)
+ {
+ ArgumentNullException.ThrowIfNull(services);
+ ArgumentNullException.ThrowIfNull(logger);
+
+ services.AddTransient(
+ typeof(INotificationHandler),
+ typeof(GeneratedRegistryNotificationHandler));
+ logger.Debug(
+ $"Registered CQRS handler {typeof(GeneratedRegistryNotificationHandler).FullName} as {typeof(INotificationHandler).FullName}.");
+ }
+}
diff --git a/GFramework.Cqrs.Tests/Cqrs/ReflectionFallbackNotificationContainer.cs b/GFramework.Cqrs.Tests/Cqrs/ReflectionFallbackNotificationContainer.cs
new file mode 100644
index 00000000..b0475e01
--- /dev/null
+++ b/GFramework.Cqrs.Tests/Cqrs/ReflectionFallbackNotificationContainer.cs
@@ -0,0 +1,32 @@
+using System;
+using System.Threading;
+using System.Threading.Tasks;
+using GFramework.Cqrs.Abstractions.Cqrs;
+
+namespace GFramework.Cqrs.Tests.Cqrs;
+
+///
+/// 用于验证“生成注册器 + reflection fallback”组合路径的私有嵌套处理器容器。
+///
+internal sealed class ReflectionFallbackNotificationContainer
+{
+ ///
+ /// 获取仅能通过反射补扫接入的私有嵌套处理器类型。
+ ///
+ public static Type ReflectionOnlyHandlerType => typeof(ReflectionOnlyGeneratedRegistryNotificationHandler);
+
+ private sealed class ReflectionOnlyGeneratedRegistryNotificationHandler
+ : INotificationHandler
+ {
+ ///
+ /// 处理测试通知。
+ ///
+ /// 通知实例。
+ /// 取消令牌。
+ /// 已完成任务。
+ public ValueTask Handle(GeneratedRegistryNotification notification, CancellationToken cancellationToken)
+ {
+ return ValueTask.CompletedTask;
+ }
+ }
+}
diff --git a/GFramework.Cqrs.Tests/Cqrs/ZetaDeterministicNotificationHandler.cs b/GFramework.Cqrs.Tests/Cqrs/ZetaDeterministicNotificationHandler.cs
new file mode 100644
index 00000000..10ff18e0
--- /dev/null
+++ b/GFramework.Cqrs.Tests/Cqrs/ZetaDeterministicNotificationHandler.cs
@@ -0,0 +1,23 @@
+using System.Threading;
+using System.Threading.Tasks;
+using GFramework.Cqrs.Abstractions.Cqrs;
+
+namespace GFramework.Cqrs.Tests.Cqrs;
+
+///
+/// 故意放在 Alpha 之前声明,用于验证注册器不会依赖源码声明顺序。
+///
+internal sealed class ZetaDeterministicNotificationHandler : INotificationHandler
+{
+ ///
+ /// 记录当前处理器已执行。
+ ///
+ /// 通知实例。
+ /// 取消令牌。
+ /// 已完成任务。
+ public ValueTask Handle(DeterministicOrderNotification notification, CancellationToken cancellationToken)
+ {
+ DeterministicNotificationHandlerState.InvocationOrder.Add(nameof(ZetaDeterministicNotificationHandler));
+ return ValueTask.CompletedTask;
+ }
+}