From 115fe65e88599c173d8175b3e4e035c3f5d00ad0 Mon Sep 17 00:00:00 2001 From: GeWuYou <95328647+GeWuYou@users.noreply.github.com> Date: Tue, 14 Apr 2026 22:54:27 +0800 Subject: [PATCH] =?UTF-8?q?docs(core):=20=E6=B7=BB=E5=8A=A0=20CQRS=20?= =?UTF-8?q?=E5=92=8C=E6=A0=B8=E5=BF=83=E6=A1=86=E6=9E=B6=E6=96=87=E6=A1=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 新增 CQRS 模块详细文档,介绍命令查询职责分离模式 - 添加核心框架架构概述和五层架构设计说明 - 补充快速开始指南和最佳实践建议 - 完善包说明和组件联动机制介绍 - 添加架构生命周期管理和模块化设计说明 --- .../Architectures/IArchitecture.cs | 12 +- .../Ioc/IIocContainer.cs | 10 +- .../ArchitectureModulesBehaviorTests.cs | 4 +- .../RegistryInitializationHookBaseTests.cs | 19 ++- ...sts.cs => CqrsCoroutineExtensionsTests.cs} | 12 +- GFramework.Core/Architectures/Architecture.cs | 14 +- .../Architectures/ArchitectureModules.cs | 16 ++- .../Extensions/CqrsCoroutineExtensions.cs | 43 ++++++ .../Extensions/MediatorCoroutineExtensions.cs | 18 +-- .../ContextAwareCqrsCommandExtensions.cs | 44 +++++++ .../Extensions/ContextAwareCqrsExtensions.cs | 123 ++++++++++++++++++ .../ContextAwareCqrsQueryExtensions.cs | 44 +++++++ .../ContextAwareMediatorCommandExtensions.cs | 22 ++-- .../ContextAwareMediatorExtensions.cs | 58 ++++----- .../ContextAwareMediatorQueryExtensions.cs | 22 ++-- GFramework.Core/Ioc/MicrosoftDiContainer.cs | 14 +- .../ContextAwareCoroutineExtensions.cs | 19 ++- docs/zh-CN/core/cqrs.md | 15 ++- docs/zh-CN/core/index.md | 4 +- 19 files changed, 402 insertions(+), 111 deletions(-) rename GFramework.Core.Tests/Coroutine/{MediatorCoroutineExtensionsTests.cs => CqrsCoroutineExtensionsTests.cs} (86%) create mode 100644 GFramework.Core/Coroutine/Extensions/CqrsCoroutineExtensions.cs create mode 100644 GFramework.Core/Extensions/ContextAwareCqrsCommandExtensions.cs create mode 100644 GFramework.Core/Extensions/ContextAwareCqrsExtensions.cs create mode 100644 GFramework.Core/Extensions/ContextAwareCqrsQueryExtensions.cs diff --git a/GFramework.Core.Abstractions/Architectures/IArchitecture.cs b/GFramework.Core.Abstractions/Architectures/IArchitecture.cs index bb855189..78303a2d 100644 --- a/GFramework.Core.Abstractions/Architectures/IArchitecture.cs +++ b/GFramework.Core.Abstractions/Architectures/IArchitecture.cs @@ -73,11 +73,21 @@ public interface IArchitecture : IAsyncInitializable, IAsyncDestroyable, IInitia /// /// 注册 CQRS 请求管道行为。 - /// 历史方法名保留了 Mediator 前缀,但当前用于配置框架内建 CQRS runtime 的行为拦截和处理逻辑。 /// 既支持实现 IPipelineBehavior<,> 的开放泛型行为类型, /// 也支持绑定到单一请求/响应对的封闭行为类型。 /// /// 行为类型,必须是引用类型 + void RegisterCqrsPipelineBehavior() + where TBehavior : class; + + /// + /// 注册 CQRS 请求管道行为。 + /// 该成员保留旧名称以兼容历史调用点,内部行为与 一致。 + /// 既支持实现 IPipelineBehavior<,> 的开放泛型行为类型, + /// 也支持绑定到单一请求/响应对的封闭行为类型。 + /// + /// 行为类型,必须是引用类型 + [Obsolete("Use RegisterCqrsPipelineBehavior() instead.")] void RegisterMediatorBehavior() where TBehavior : class; diff --git a/GFramework.Core.Abstractions/Ioc/IIocContainer.cs b/GFramework.Core.Abstractions/Ioc/IIocContainer.cs index d00211ed..0e55908a 100644 --- a/GFramework.Core.Abstractions/Ioc/IIocContainer.cs +++ b/GFramework.Core.Abstractions/Ioc/IIocContainer.cs @@ -90,9 +90,17 @@ public interface IIocContainer : IContextAware /// /// 注册 CQRS 请求管道行为。 - /// 历史方法名保留了 Mediator 前缀,但当前用于配置框架内建 CQRS runtime 的行为拦截和处理逻辑。 /// /// 行为类型,必须是引用类型 + void RegisterCqrsPipelineBehavior() + where TBehavior : class; + + /// + /// 注册 CQRS 请求管道行为。 + /// 该成员保留旧名称以兼容历史调用点,内部行为与 一致。 + /// + /// 行为类型,必须是引用类型 + [Obsolete("Use RegisterCqrsPipelineBehavior() instead.")] void RegisterMediatorBehavior() where TBehavior : class; diff --git a/GFramework.Core.Tests/Architectures/ArchitectureModulesBehaviorTests.cs b/GFramework.Core.Tests/Architectures/ArchitectureModulesBehaviorTests.cs index bf6566b4..c5c0b685 100644 --- a/GFramework.Core.Tests/Architectures/ArchitectureModulesBehaviorTests.cs +++ b/GFramework.Core.Tests/Architectures/ArchitectureModulesBehaviorTests.cs @@ -59,10 +59,10 @@ public class ArchitectureModulesBehaviorTests /// 验证注册的 CQRS 行为会参与请求管道执行。 /// [Test] - public async Task RegisterMediatorBehavior_Should_Apply_Pipeline_Behavior_To_Request() + public async Task RegisterCqrsPipelineBehavior_Should_Apply_Pipeline_Behavior_To_Request() { var architecture = new ModuleTestArchitecture(target => - target.RegisterMediatorBehavior>()); + target.RegisterCqrsPipelineBehavior>()); await architecture.InitializeAsync(); diff --git a/GFramework.Core.Tests/Architectures/RegistryInitializationHookBaseTests.cs b/GFramework.Core.Tests/Architectures/RegistryInitializationHookBaseTests.cs index 4e517194..38e06805 100644 --- a/GFramework.Core.Tests/Architectures/RegistryInitializationHookBaseTests.cs +++ b/GFramework.Core.Tests/Architectures/RegistryInitializationHookBaseTests.cs @@ -5,7 +5,6 @@ using GFramework.Core.Abstractions.Model; using GFramework.Core.Abstractions.Systems; using GFramework.Core.Abstractions.Utility; using GFramework.Core.Architectures; -using Microsoft.Extensions.DependencyInjection; namespace GFramework.Core.Tests.Architectures; @@ -181,11 +180,17 @@ public class TestArchitectureWithRegistry : IArchitecture throw new NotImplementedException(); } - public void RegisterMediatorBehavior() where TBehavior : class + public void RegisterCqrsPipelineBehavior() where TBehavior : class { throw new NotImplementedException(); } + [Obsolete("Use RegisterCqrsPipelineBehavior() instead.")] + public void RegisterMediatorBehavior() where TBehavior : class + { + RegisterCqrsPipelineBehavior(); + } + public IArchitectureModule InstallModule(IArchitectureModule module) { throw new NotImplementedException(); @@ -306,11 +311,17 @@ public class TestArchitectureWithoutRegistry : IArchitecture throw new NotImplementedException(); } - public void RegisterMediatorBehavior() where TBehavior : class + public void RegisterCqrsPipelineBehavior() where TBehavior : class { throw new NotImplementedException(); } + [Obsolete("Use RegisterCqrsPipelineBehavior() instead.")] + public void RegisterMediatorBehavior() where TBehavior : class + { + RegisterCqrsPipelineBehavior(); + } + public IArchitectureModule InstallModule(IArchitectureModule module) { throw new NotImplementedException(); @@ -363,4 +374,4 @@ public class TestArchitectureWithoutRegistry : IArchitecture public void RegisterLifecycleHook(IArchitectureLifecycleHook hook) { } -} \ No newline at end of file +} diff --git a/GFramework.Core.Tests/Coroutine/MediatorCoroutineExtensionsTests.cs b/GFramework.Core.Tests/Coroutine/CqrsCoroutineExtensionsTests.cs similarity index 86% rename from GFramework.Core.Tests/Coroutine/MediatorCoroutineExtensionsTests.cs rename to GFramework.Core.Tests/Coroutine/CqrsCoroutineExtensionsTests.cs index 9dfa7b1e..2adba37a 100644 --- a/GFramework.Core.Tests/Coroutine/MediatorCoroutineExtensionsTests.cs +++ b/GFramework.Core.Tests/Coroutine/CqrsCoroutineExtensionsTests.cs @@ -15,17 +15,17 @@ using GFramework.Core.Abstractions.Architectures; using GFramework.Core.Abstractions.Coroutine; using GFramework.Core.Abstractions.Cqrs; using GFramework.Core.Abstractions.Rule; -using GFramework.Core.Coroutine.Extensions; +using GFramework.Core.Cqrs.Extensions; namespace GFramework.Core.Tests.Coroutine; /// -/// 的单元测试类。 -/// 验证历史命名的协程扩展已切到框架内建 CQRS runtime, +/// 的单元测试类。 +/// 验证新的 CQRS 协程扩展直接走框架内建 CQRS runtime, /// 并确保协程对命令调度异常的传播行为保持稳定。 /// [TestFixture] -public class MediatorCoroutineExtensionsTests +public class CqrsCoroutineExtensionsTests { /// /// 验证SendCommandCoroutine应该返回IEnumerator @@ -40,7 +40,7 @@ public class MediatorCoroutineExtensionsTests .Setup(ctx => ctx.SendAsync(command, It.IsAny())) .Returns(ValueTask.CompletedTask); - var coroutine = MediatorCoroutineExtensions.SendCommandCoroutine(contextAware, command); + var coroutine = CqrsCoroutineExtensions.SendCommandCoroutine(contextAware, command); Assert.That(coroutine, Is.InstanceOf>()); } @@ -59,7 +59,7 @@ public class MediatorCoroutineExtensionsTests .Setup(ctx => ctx.SendAsync(command, It.IsAny())) .Returns(new ValueTask(Task.FromException(expectedException))); - var coroutine = MediatorCoroutineExtensions.SendCommandCoroutine(contextAware, command); + var coroutine = CqrsCoroutineExtensions.SendCommandCoroutine(contextAware, command); Assert.That(coroutine.MoveNext(), Is.True); var exception = Assert.Throws(() => coroutine.MoveNext()); diff --git a/GFramework.Core/Architectures/Architecture.cs b/GFramework.Core/Architectures/Architecture.cs index ac4fa2dc..ec571ee8 100644 --- a/GFramework.Core/Architectures/Architecture.cs +++ b/GFramework.Core/Architectures/Architecture.cs @@ -146,13 +146,23 @@ public abstract class Architecture : IArchitecture /// /// 注册 CQRS 请求管道行为。 - /// 历史方法名保留了 Mediator 前缀,但当前用于配置框架内建 CQRS runtime 的行为拦截和处理逻辑。 /// 可以传入开放泛型行为类型,也可以传入绑定到特定请求的封闭行为类型。 /// /// 行为类型,必须是引用类型 + public void RegisterCqrsPipelineBehavior() where TBehavior : class + { + _modules.RegisterCqrsPipelineBehavior(); + } + + /// + /// 注册 CQRS 请求管道行为。 + /// 该成员保留旧名称以兼容历史调用点,内部行为与 一致。 + /// + /// 行为类型,必须是引用类型 + [Obsolete("Use RegisterCqrsPipelineBehavior() instead.")] public void RegisterMediatorBehavior() where TBehavior : class { - _modules.RegisterMediatorBehavior(); + RegisterCqrsPipelineBehavior(); } /// diff --git a/GFramework.Core/Architectures/ArchitectureModules.cs b/GFramework.Core/Architectures/ArchitectureModules.cs index d02f39e2..7563e276 100644 --- a/GFramework.Core/Architectures/ArchitectureModules.cs +++ b/GFramework.Core/Architectures/ArchitectureModules.cs @@ -14,14 +14,24 @@ internal sealed class ArchitectureModules( { /// /// 注册 CQRS 请求管道行为。 - /// 历史方法名保留了 Mediator 前缀,但当前用于配置框架内建 CQRS runtime 的行为拦截和处理逻辑。 /// 支持开放泛型行为类型和针对单一请求的封闭行为类型。 /// /// 行为类型,必须是引用类型 - public void RegisterMediatorBehavior() where TBehavior : class + public void RegisterCqrsPipelineBehavior() where TBehavior : class { logger.Debug($"Registering CQRS pipeline behavior: {typeof(TBehavior).Name}"); - services.Container.RegisterMediatorBehavior(); + services.Container.RegisterCqrsPipelineBehavior(); + } + + /// + /// 注册 CQRS 请求管道行为。 + /// 该成员保留旧名称以兼容历史调用点,内部行为与 一致。 + /// + /// 行为类型,必须是引用类型 + [Obsolete("Use RegisterCqrsPipelineBehavior() instead.")] + public void RegisterMediatorBehavior() where TBehavior : class + { + RegisterCqrsPipelineBehavior(); } /// diff --git a/GFramework.Core/Coroutine/Extensions/CqrsCoroutineExtensions.cs b/GFramework.Core/Coroutine/Extensions/CqrsCoroutineExtensions.cs new file mode 100644 index 00000000..55e6a67f --- /dev/null +++ b/GFramework.Core/Coroutine/Extensions/CqrsCoroutineExtensions.cs @@ -0,0 +1,43 @@ +using GFramework.Core.Abstractions.Coroutine; +using GFramework.Core.Abstractions.Cqrs; +using GFramework.Core.Abstractions.Rule; +using GFramework.Core.Coroutine.Extensions; + +namespace GFramework.Core.Cqrs.Extensions; + +/// +/// 提供 CQRS 命令与协程集成的扩展方法。 +/// 这些扩展直接走架构上下文的内建 CQRS runtime,不依赖外部 Mediator 服务。 +/// +public static class CqrsCoroutineExtensions +{ + /// + /// 以协程方式发送无返回值 CQRS 命令并处理可能的异常。 + /// + /// 命令类型。 + /// 上下文感知对象,用于获取架构上下文。 + /// 要发送的命令对象。 + /// 发生异常时的回调处理函数。 + /// 协程枚举器,用于协程执行。 + public static IEnumerator SendCommandCoroutine( + this IContextAware contextAware, + TCommand command, + Action? onError = null) + where TCommand : IRequest + { + ArgumentNullException.ThrowIfNull(contextAware); + ArgumentNullException.ThrowIfNull(command); + + var task = contextAware.GetContext().SendAsync(command).AsTask(); + + yield return task.AsCoroutineInstruction(); + + if (!task.IsFaulted) + yield break; + + if (onError != null) + onError.Invoke(task.Exception!); + else + throw task.Exception!.InnerException ?? task.Exception; + } +} diff --git a/GFramework.Core/Coroutine/Extensions/MediatorCoroutineExtensions.cs b/GFramework.Core/Coroutine/Extensions/MediatorCoroutineExtensions.cs index 42ff1ce2..91ed0238 100644 --- a/GFramework.Core/Coroutine/Extensions/MediatorCoroutineExtensions.cs +++ b/GFramework.Core/Coroutine/Extensions/MediatorCoroutineExtensions.cs @@ -14,14 +14,15 @@ using GFramework.Core.Abstractions.Coroutine; using GFramework.Core.Abstractions.Cqrs; using GFramework.Core.Abstractions.Rule; +using GFramework.Core.Cqrs.Extensions; namespace GFramework.Core.Coroutine.Extensions; /// /// 提供 CQRS 命令与协程集成的扩展方法。 -/// 历史命名保留了 Mediator 前缀,但当前实现直接走 返回的 -/// CQRS 入口,不再依赖外部 Mediator 服务。 +/// 该类型保留旧名称以兼容历史调用点;新代码应改用 。 /// +[Obsolete("Use GFramework.Core.Cqrs.Extensions.CqrsCoroutineExtensions instead.")] public static class MediatorCoroutineExtensions { /// @@ -38,17 +39,6 @@ public static class MediatorCoroutineExtensions Action? onError = null) where TCommand : IRequest { - ArgumentNullException.ThrowIfNull(contextAware); - ArgumentNullException.ThrowIfNull(command); - - var task = contextAware.GetContext().SendAsync(command).AsTask(); - - yield return task.AsCoroutineInstruction(); - - if (!task.IsFaulted) yield break; - if (onError != null) - onError.Invoke(task.Exception!); - else - throw task.Exception!.InnerException ?? task.Exception; + return CqrsCoroutineExtensions.SendCommandCoroutine(contextAware, command, onError); } } diff --git a/GFramework.Core/Extensions/ContextAwareCqrsCommandExtensions.cs b/GFramework.Core/Extensions/ContextAwareCqrsCommandExtensions.cs new file mode 100644 index 00000000..5f86f4e5 --- /dev/null +++ b/GFramework.Core/Extensions/ContextAwareCqrsCommandExtensions.cs @@ -0,0 +1,44 @@ +using GFramework.Core.Abstractions.Cqrs.Command; +using GFramework.Core.Abstractions.Rule; + +namespace GFramework.Core.Cqrs.Extensions; + +/// +/// 提供对 接口的 CQRS 命令扩展方法。 +/// +public static class ContextAwareCqrsCommandExtensions +{ + /// + /// 发送命令的同步版本(不推荐,仅用于兼容同步调用链)。 + /// + /// 命令响应类型。 + /// 实现 接口的对象。 + /// 要发送的命令对象。 + /// 命令执行结果。 + public static TResponse SendCommand(this IContextAware contextAware, ICommand command) + { + ArgumentNullException.ThrowIfNull(contextAware); + ArgumentNullException.ThrowIfNull(command); + + return contextAware.GetContext().SendCommand(command); + } + + /// + /// 异步发送命令并返回结果。 + /// + /// 命令响应类型。 + /// 实现 接口的对象。 + /// 要发送的命令对象。 + /// 取消令牌,用于取消操作。 + /// 包含命令执行结果的 + public static ValueTask SendCommandAsync( + this IContextAware contextAware, + ICommand command, + CancellationToken cancellationToken = default) + { + ArgumentNullException.ThrowIfNull(contextAware); + ArgumentNullException.ThrowIfNull(command); + + return contextAware.GetContext().SendCommandAsync(command, cancellationToken); + } +} diff --git a/GFramework.Core/Extensions/ContextAwareCqrsExtensions.cs b/GFramework.Core/Extensions/ContextAwareCqrsExtensions.cs new file mode 100644 index 00000000..64f9d0e1 --- /dev/null +++ b/GFramework.Core/Extensions/ContextAwareCqrsExtensions.cs @@ -0,0 +1,123 @@ +using GFramework.Core.Abstractions.Cqrs; +using GFramework.Core.Abstractions.Rule; + +namespace GFramework.Core.Cqrs.Extensions; + +/// +/// 提供对 接口的 CQRS 统一扩展方法。 +/// 这些扩展直接委托给架构上下文的内建 CQRS runtime,作为新的中性命名入口。 +/// +public static class ContextAwareCqrsExtensions +{ + /// + /// 发送请求(统一处理 Command/Query)。 + /// + /// 响应类型。 + /// 实现 接口的对象。 + /// 要发送的请求。 + /// 取消令牌。 + /// 请求结果。 + public static ValueTask SendRequestAsync( + this IContextAware contextAware, + IRequest request, + CancellationToken cancellationToken = default) + { + ArgumentNullException.ThrowIfNull(contextAware); + ArgumentNullException.ThrowIfNull(request); + + return contextAware.GetContext().SendRequestAsync(request, cancellationToken); + } + + /// + /// 发送请求(同步版本,不推荐)。 + /// + /// 响应类型。 + /// 实现 接口的对象。 + /// 要发送的请求。 + /// 请求结果。 + public static TResponse SendRequest(this IContextAware contextAware, IRequest request) + { + ArgumentNullException.ThrowIfNull(contextAware); + ArgumentNullException.ThrowIfNull(request); + + return contextAware.GetContext().SendRequest(request); + } + + /// + /// 发布通知(一对多事件)。 + /// + /// 通知类型。 + /// 实现 接口的对象。 + /// 要发布的通知。 + /// 取消令牌。 + /// 异步任务。 + public static ValueTask PublishAsync( + this IContextAware contextAware, + TNotification notification, + CancellationToken cancellationToken = default) + where TNotification : INotification + { + ArgumentNullException.ThrowIfNull(contextAware); + ArgumentNullException.ThrowIfNull(notification); + + return contextAware.GetContext().PublishAsync(notification, cancellationToken); + } + + /// + /// 创建流式请求。 + /// + /// 响应类型。 + /// 实现 接口的对象。 + /// 流式请求。 + /// 取消令牌。 + /// 异步响应流。 + public static IAsyncEnumerable CreateStream( + this IContextAware contextAware, + IStreamRequest request, + CancellationToken cancellationToken = default) + { + ArgumentNullException.ThrowIfNull(contextAware); + ArgumentNullException.ThrowIfNull(request); + + return contextAware.GetContext().CreateStream(request, cancellationToken); + } + + /// + /// 发送无返回值命令。 + /// + /// 命令类型。 + /// 实现 接口的对象。 + /// 要发送的命令。 + /// 取消令牌。 + /// 异步任务。 + public static ValueTask SendAsync( + this IContextAware contextAware, + TCommand command, + CancellationToken cancellationToken = default) + where TCommand : IRequest + { + ArgumentNullException.ThrowIfNull(contextAware); + ArgumentNullException.ThrowIfNull(command); + + return contextAware.GetContext().SendAsync(command, cancellationToken); + } + + /// + /// 发送带返回值命令。 + /// + /// 响应类型。 + /// 实现 接口的对象。 + /// 要发送的命令。 + /// 取消令牌。 + /// 命令执行结果。 + public static ValueTask SendAsync( + this IContextAware contextAware, + IRequest command, + CancellationToken cancellationToken = default) + { + ArgumentNullException.ThrowIfNull(contextAware); + ArgumentNullException.ThrowIfNull(command); + + return contextAware.GetContext().SendAsync(command, cancellationToken); + } +} diff --git a/GFramework.Core/Extensions/ContextAwareCqrsQueryExtensions.cs b/GFramework.Core/Extensions/ContextAwareCqrsQueryExtensions.cs new file mode 100644 index 00000000..42905215 --- /dev/null +++ b/GFramework.Core/Extensions/ContextAwareCqrsQueryExtensions.cs @@ -0,0 +1,44 @@ +using GFramework.Core.Abstractions.Cqrs.Query; +using GFramework.Core.Abstractions.Rule; + +namespace GFramework.Core.Cqrs.Extensions; + +/// +/// 提供对 接口的 CQRS 查询扩展方法。 +/// +public static class ContextAwareCqrsQueryExtensions +{ + /// + /// 发送查询的同步版本(不推荐,仅用于兼容同步调用链)。 + /// + /// 查询响应类型。 + /// 实现 接口的对象。 + /// 要发送的查询对象。 + /// 查询结果。 + public static TResponse SendQuery(this IContextAware contextAware, IQuery query) + { + ArgumentNullException.ThrowIfNull(contextAware); + ArgumentNullException.ThrowIfNull(query); + + return contextAware.GetContext().SendQuery(query); + } + + /// + /// 异步发送查询并返回结果。 + /// + /// 查询响应类型。 + /// 实现 接口的对象。 + /// 要发送的查询对象。 + /// 取消令牌,用于取消操作。 + /// 包含查询结果的 + public static ValueTask SendQueryAsync( + this IContextAware contextAware, + IQuery query, + CancellationToken cancellationToken = default) + { + ArgumentNullException.ThrowIfNull(contextAware); + ArgumentNullException.ThrowIfNull(query); + + return contextAware.GetContext().SendQueryAsync(query, cancellationToken); + } +} diff --git a/GFramework.Core/Extensions/ContextAwareMediatorCommandExtensions.cs b/GFramework.Core/Extensions/ContextAwareMediatorCommandExtensions.cs index 881741e7..9fc9311b 100644 --- a/GFramework.Core/Extensions/ContextAwareMediatorCommandExtensions.cs +++ b/GFramework.Core/Extensions/ContextAwareMediatorCommandExtensions.cs @@ -1,11 +1,14 @@ -using GFramework.Core.Abstractions.Rule; using GFramework.Core.Abstractions.Cqrs.Command; +using GFramework.Core.Abstractions.Rule; +using GFramework.Core.Cqrs.Extensions; namespace GFramework.Core.Extensions; /// -/// 提供对 IContextAware 接口的 CQRS 命令扩展方法。 +/// 提供对 接口的 CQRS 命令扩展方法。 +/// 该类型保留旧名称以兼容历史调用点;新代码应改用 。 /// +[Obsolete("Use GFramework.Core.Cqrs.Extensions.ContextAwareCqrsCommandExtensions instead.")] public static class ContextAwareMediatorCommandExtensions { /// @@ -19,11 +22,7 @@ public static class ContextAwareMediatorCommandExtensions public static TResponse SendCommand(this IContextAware contextAware, ICommand command) { - ArgumentNullException.ThrowIfNull(contextAware); - ArgumentNullException.ThrowIfNull(command); - - var context = contextAware.GetContext(); - return context.SendCommand(command); + return ContextAwareCqrsCommandExtensions.SendCommand(contextAware, command); } /// @@ -38,10 +37,9 @@ public static class ContextAwareMediatorCommandExtensions public static ValueTask SendCommandAsync(this IContextAware contextAware, ICommand command, CancellationToken cancellationToken = default) { - ArgumentNullException.ThrowIfNull(contextAware); - ArgumentNullException.ThrowIfNull(command); - - var context = contextAware.GetContext(); - return context.SendCommandAsync(command, cancellationToken); + return ContextAwareCqrsCommandExtensions.SendCommandAsync( + contextAware, + command, + cancellationToken); } } diff --git a/GFramework.Core/Extensions/ContextAwareMediatorExtensions.cs b/GFramework.Core/Extensions/ContextAwareMediatorExtensions.cs index 1661d87b..4b63e223 100644 --- a/GFramework.Core/Extensions/ContextAwareMediatorExtensions.cs +++ b/GFramework.Core/Extensions/ContextAwareMediatorExtensions.cs @@ -1,11 +1,14 @@ -using GFramework.Core.Abstractions.Rule; using GFramework.Core.Abstractions.Cqrs; +using GFramework.Core.Abstractions.Rule; +using GFramework.Core.Cqrs.Extensions; namespace GFramework.Core.Extensions; /// -/// 提供对 IContextAware 接口的 CQRS 统一接口扩展方法。 +/// 提供对 接口的 CQRS 统一接口扩展方法。 +/// 该类型保留旧名称以兼容历史调用点;新代码应改用 。 /// +[Obsolete("Use GFramework.Core.Cqrs.Extensions.ContextAwareCqrsExtensions instead.")] public static class ContextAwareMediatorExtensions { /// @@ -20,11 +23,10 @@ public static class ContextAwareMediatorExtensions public static ValueTask SendRequestAsync(this IContextAware contextAware, IRequest request, CancellationToken cancellationToken = default) { - ArgumentNullException.ThrowIfNull(contextAware); - ArgumentNullException.ThrowIfNull(request); - - var context = contextAware.GetContext(); - return context.SendRequestAsync(request, cancellationToken); + return ContextAwareCqrsExtensions.SendRequestAsync( + contextAware, + request, + cancellationToken); } /// @@ -38,11 +40,7 @@ public static class ContextAwareMediatorExtensions public static TResponse SendRequest(this IContextAware contextAware, IRequest request) { - ArgumentNullException.ThrowIfNull(contextAware); - ArgumentNullException.ThrowIfNull(request); - - var context = contextAware.GetContext(); - return context.SendRequest(request); + return ContextAwareCqrsExtensions.SendRequest(contextAware, request); } /// @@ -58,11 +56,10 @@ public static class ContextAwareMediatorExtensions TNotification notification, CancellationToken cancellationToken = default) where TNotification : INotification { - ArgumentNullException.ThrowIfNull(contextAware); - ArgumentNullException.ThrowIfNull(notification); - - var context = contextAware.GetContext(); - return context.PublishAsync(notification, cancellationToken); + return ContextAwareCqrsExtensions.PublishAsync( + contextAware, + notification, + cancellationToken); } /// @@ -77,11 +74,10 @@ public static class ContextAwareMediatorExtensions public static IAsyncEnumerable CreateStream(this IContextAware contextAware, IStreamRequest request, CancellationToken cancellationToken = default) { - ArgumentNullException.ThrowIfNull(contextAware); - ArgumentNullException.ThrowIfNull(request); - - var context = contextAware.GetContext(); - return context.CreateStream(request, cancellationToken); + return ContextAwareCqrsExtensions.CreateStream( + contextAware, + request, + cancellationToken); } /// @@ -97,11 +93,10 @@ public static class ContextAwareMediatorExtensions CancellationToken cancellationToken = default) where TCommand : IRequest { - ArgumentNullException.ThrowIfNull(contextAware); - ArgumentNullException.ThrowIfNull(command); - - var context = contextAware.GetContext(); - return context.SendAsync(command, cancellationToken); + return ContextAwareCqrsExtensions.SendAsync( + contextAware, + command, + cancellationToken); } /// @@ -116,10 +111,9 @@ public static class ContextAwareMediatorExtensions public static ValueTask SendAsync(this IContextAware contextAware, IRequest command, CancellationToken cancellationToken = default) { - ArgumentNullException.ThrowIfNull(contextAware); - ArgumentNullException.ThrowIfNull(command); - - var context = contextAware.GetContext(); - return context.SendAsync(command, cancellationToken); + return ContextAwareCqrsExtensions.SendAsync( + contextAware, + command, + cancellationToken); } } diff --git a/GFramework.Core/Extensions/ContextAwareMediatorQueryExtensions.cs b/GFramework.Core/Extensions/ContextAwareMediatorQueryExtensions.cs index 5a4bfeb6..be2d70e1 100644 --- a/GFramework.Core/Extensions/ContextAwareMediatorQueryExtensions.cs +++ b/GFramework.Core/Extensions/ContextAwareMediatorQueryExtensions.cs @@ -1,11 +1,14 @@ -using GFramework.Core.Abstractions.Rule; using GFramework.Core.Abstractions.Cqrs.Query; +using GFramework.Core.Abstractions.Rule; +using GFramework.Core.Cqrs.Extensions; namespace GFramework.Core.Extensions; /// -/// 提供对 IContextAware 接口的 CQRS 查询扩展方法。 +/// 提供对 接口的 CQRS 查询扩展方法。 +/// 该类型保留旧名称以兼容历史调用点;新代码应改用 。 /// +[Obsolete("Use GFramework.Core.Cqrs.Extensions.ContextAwareCqrsQueryExtensions instead.")] public static class ContextAwareMediatorQueryExtensions { /// @@ -18,11 +21,7 @@ public static class ContextAwareMediatorQueryExtensions /// 当 contextAware 或 query 为 null 时抛出 public static TResponse SendQuery(this IContextAware contextAware, IQuery query) { - ArgumentNullException.ThrowIfNull(contextAware); - ArgumentNullException.ThrowIfNull(query); - - var context = contextAware.GetContext(); - return context.SendQuery(query); + return ContextAwareCqrsQueryExtensions.SendQuery(contextAware, query); } /// @@ -37,10 +36,9 @@ public static class ContextAwareMediatorQueryExtensions public static ValueTask SendQueryAsync(this IContextAware contextAware, IQuery query, CancellationToken cancellationToken = default) { - ArgumentNullException.ThrowIfNull(contextAware); - ArgumentNullException.ThrowIfNull(query); - - var context = contextAware.GetContext(); - return context.SendQueryAsync(query, cancellationToken); + return ContextAwareCqrsQueryExtensions.SendQueryAsync( + contextAware, + query, + cancellationToken); } } diff --git a/GFramework.Core/Ioc/MicrosoftDiContainer.cs b/GFramework.Core/Ioc/MicrosoftDiContainer.cs index 6b45a09e..69b46720 100644 --- a/GFramework.Core/Ioc/MicrosoftDiContainer.cs +++ b/GFramework.Core/Ioc/MicrosoftDiContainer.cs @@ -310,12 +310,11 @@ public class MicrosoftDiContainer(IServiceCollection? serviceCollection = null) /// /// 注册 CQRS 请求管道行为。 - /// 历史方法名保留了 Mediator 前缀,但当前用于配置框架内建 CQRS runtime 的行为拦截和处理逻辑。 /// 同时支持开放泛型行为类型和已闭合的具体行为类型, /// 以兼容通用行为和针对单一请求的专用行为两种注册方式。 /// /// 行为类型,必须是引用类型 - public void RegisterMediatorBehavior() where TBehavior : class + public void RegisterCqrsPipelineBehavior() where TBehavior : class { _lock.EnterWriteLock(); try @@ -358,6 +357,17 @@ public class MicrosoftDiContainer(IServiceCollection? serviceCollection = null) } } + /// + /// 注册 CQRS 请求管道行为。 + /// 该成员保留旧名称以兼容历史调用点,内部行为与 一致。 + /// + /// 行为类型,必须是引用类型 + [Obsolete("Use RegisterCqrsPipelineBehavior() instead.")] + public void RegisterMediatorBehavior() where TBehavior : class + { + RegisterCqrsPipelineBehavior(); + } + /// /// 配置服务 /// diff --git a/GFramework.Godot/Coroutine/ContextAwareCoroutineExtensions.cs b/GFramework.Godot/Coroutine/ContextAwareCoroutineExtensions.cs index d97d08a7..5d1a3485 100644 --- a/GFramework.Godot/Coroutine/ContextAwareCoroutineExtensions.cs +++ b/GFramework.Godot/Coroutine/ContextAwareCoroutineExtensions.cs @@ -2,9 +2,6 @@ using GFramework.Core.Abstractions.Cqrs.Command; using GFramework.Core.Abstractions.Cqrs.Query; using GFramework.Core.Abstractions.Rule; -using GFramework.Core.Coroutine; -using GFramework.Core.Coroutine.Extensions; -using GFramework.Core.Extensions; namespace GFramework.Godot.Coroutine; @@ -29,8 +26,8 @@ public static class ContextAwareCoroutineExtensions string? tag = null, CancellationToken cancellationToken = default) { - return contextAware - .SendCommandAsync(command, cancellationToken) + return Core.Cqrs.Extensions.ContextAwareCqrsCommandExtensions + .SendCommandAsync(contextAware, command, cancellationToken) .AsTask() .ToCoroutineEnumerator() .RunCoroutine(segment, tag); @@ -53,8 +50,8 @@ public static class ContextAwareCoroutineExtensions string? tag = null, CancellationToken cancellationToken = default) { - return contextAware - .SendCommandAsync(command, cancellationToken) + return Core.Cqrs.Extensions.ContextAwareCqrsCommandExtensions + .SendCommandAsync(contextAware, command, cancellationToken) .AsTask() .ToCoroutineEnumerator() .RunCoroutine(segment, tag); @@ -77,8 +74,8 @@ public static class ContextAwareCoroutineExtensions string? tag = null, CancellationToken cancellationToken = default) { - return contextAware - .SendQueryAsync(query, cancellationToken) + return Core.Cqrs.Extensions.ContextAwareCqrsQueryExtensions + .SendQueryAsync(contextAware, query, cancellationToken) .AsTask() .ToCoroutineEnumerator() .RunCoroutine(segment, tag); @@ -100,8 +97,8 @@ public static class ContextAwareCoroutineExtensions string? tag = null, CancellationToken cancellationToken = default) { - return contextAware - .PublishAsync(notification, cancellationToken) + return Core.Cqrs.Extensions.ContextAwareCqrsExtensions + .PublishAsync(contextAware, notification, cancellationToken) .AsTask() .ToCoroutineEnumerator() .RunCoroutine(segment, tag); diff --git a/docs/zh-CN/core/cqrs.md b/docs/zh-CN/core/cqrs.md index b92566d1..742d2ef8 100644 --- a/docs/zh-CN/core/cqrs.md +++ b/docs/zh-CN/core/cqrs.md @@ -212,15 +212,16 @@ public class GameArchitecture : Architecture protected override void Init() { // 注册通用开放泛型行为 - RegisterMediatorBehavior>(); - RegisterMediatorBehavior>(); + RegisterCqrsPipelineBehavior>(); + RegisterCqrsPipelineBehavior>(); // 处理器会自动通过依赖注入注册 } } ``` -`RegisterMediatorBehavior()` 是保留的兼容名称,当前用于注册框架内建 CQRS pipeline,支持两种形式: +`RegisterCqrsPipelineBehavior()` 是推荐入口;旧的 `RegisterMediatorBehavior()` +仅作为兼容名称保留。当前接口支持两种形式: - 开放泛型行为,例如 `LoggingBehavior<,>`,用于匹配所有请求 - 封闭行为类型,例如某个只服务于单一请求的 `SpecialBehavior` @@ -377,8 +378,8 @@ public class PerformanceBehavior : IPipelineBehavior>(); -RegisterMediatorBehavior>(); +RegisterCqrsPipelineBehavior>(); +RegisterCqrsPipelineBehavior>(); ``` ### 验证行为 @@ -471,8 +472,8 @@ await foreach (var player in stream) 4. **使用 Behaviors 处理横切关注点**:日志、性能、验证等 ```csharp - RegisterMediatorBehavior>(); - RegisterMediatorBehavior>(); + RegisterCqrsPipelineBehavior>(); + RegisterCqrsPipelineBehavior>(); ``` 5. **保持处理器简单**:一个处理器只做一件事 diff --git a/docs/zh-CN/core/index.md b/docs/zh-CN/core/index.md index 98455237..5c4837bf 100644 --- a/docs/zh-CN/core/index.md +++ b/docs/zh-CN/core/index.md @@ -396,12 +396,12 @@ public class PlayerController : IController **核心功能**: - 模块安装 (IArchitectureModule) -- CQRS 管道行为注册(历史 API 名称仍为 `RegisterMediatorBehavior`) +- CQRS 管道行为注册(推荐 API 为 `RegisterCqrsPipelineBehavior`) **关键方法**: - `InstallModule()` - 安装模块 -- `RegisterMediatorBehavior()` - 注册 CQRS 管道行为 +- `RegisterCqrsPipelineBehavior()` - 注册 CQRS 管道行为 #### 设计优势