diff --git a/CLAUDE.md b/CLAUDE.md index 570606c7..1962098f 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -73,7 +73,8 @@ Architecture 负责统一生命周期编排,核心阶段包括: ### CQRS -命令与查询分离,支持同步与异步执行。Mediator 模式通过源码生成器集成,以减少模板代码并保持调用路径清晰。 +命令与查询分离,支持同步与异步执行。当前版本内建自有 CQRS runtime、行为管道和 handler 自动注册;公开 API 里仍保留少量历史 +`Mediator` 命名以兼容旧调用点。 ### EventBus diff --git a/GFramework.Core.Abstractions/Architectures/IArchitecture.cs b/GFramework.Core.Abstractions/Architectures/IArchitecture.cs index 0055d3fe..bb855189 100644 --- a/GFramework.Core.Abstractions/Architectures/IArchitecture.cs +++ b/GFramework.Core.Abstractions/Architectures/IArchitecture.cs @@ -2,7 +2,6 @@ using GFramework.Core.Abstractions.Lifecycle; using GFramework.Core.Abstractions.Model; using GFramework.Core.Abstractions.Systems; using GFramework.Core.Abstractions.Utility; -using Microsoft.Extensions.DependencyInjection; namespace GFramework.Core.Abstractions.Architectures; @@ -73,8 +72,8 @@ public interface IArchitecture : IAsyncInitializable, IAsyncDestroyable, IInitia void RegisterUtility(Action? onCreated = null) where T : class, IUtility; /// - /// 注册中介行为管道 - /// 用于配置Mediator框架的行为拦截和处理逻辑。 + /// 注册 CQRS 请求管道行为。 + /// 历史方法名保留了 Mediator 前缀,但当前用于配置框架内建 CQRS runtime 的行为拦截和处理逻辑。 /// 既支持实现 IPipelineBehavior<,> 的开放泛型行为类型, /// 也支持绑定到单一请求/响应对的封闭行为类型。 /// @@ -101,4 +100,4 @@ public interface IArchitecture : IAsyncInitializable, IAsyncDestroyable, IInitia /// /// 表示异步等待操作的任务 Task WaitUntilReadyAsync(); -} \ No newline at end of file +} diff --git a/GFramework.Core.Abstractions/GFramework.Core.Abstractions.csproj b/GFramework.Core.Abstractions/GFramework.Core.Abstractions.csproj index 8ec77b72..84d53f63 100644 --- a/GFramework.Core.Abstractions/GFramework.Core.Abstractions.csproj +++ b/GFramework.Core.Abstractions/GFramework.Core.Abstractions.csproj @@ -26,6 +26,6 @@ all runtime; build; native; contentfiles; analyzers - + diff --git a/GFramework.Core.Abstractions/Ioc/IIocContainer.cs b/GFramework.Core.Abstractions/Ioc/IIocContainer.cs index b61d0f3a..d00211ed 100644 --- a/GFramework.Core.Abstractions/Ioc/IIocContainer.cs +++ b/GFramework.Core.Abstractions/Ioc/IIocContainer.cs @@ -1,6 +1,5 @@ using GFramework.Core.Abstractions.Rule; using GFramework.Core.Abstractions.Systems; -using Microsoft.Extensions.DependencyInjection; namespace GFramework.Core.Abstractions.Ioc; @@ -90,8 +89,8 @@ public interface IIocContainer : IContextAware void RegisterFactory(Func factory) where TService : class; /// - /// 注册中介行为管道 - /// 用于配置Mediator框架的行为拦截和处理逻辑 + /// 注册 CQRS 请求管道行为。 + /// 历史方法名保留了 Mediator 前缀,但当前用于配置框架内建 CQRS runtime 的行为拦截和处理逻辑。 /// /// 行为类型,必须是引用类型 void RegisterMediatorBehavior() @@ -227,4 +226,4 @@ public interface IIocContainer : IContextAware IServiceScope CreateScope(); #endregion -} \ No newline at end of file +} diff --git a/GFramework.Core.Tests/Architectures/ArchitectureServicesTests.cs b/GFramework.Core.Tests/Architectures/ArchitectureServicesTests.cs index 512e8a55..94b749b6 100644 --- a/GFramework.Core.Tests/Architectures/ArchitectureServicesTests.cs +++ b/GFramework.Core.Tests/Architectures/ArchitectureServicesTests.cs @@ -1,5 +1,6 @@ using GFramework.Core.Abstractions.Architectures; using GFramework.Core.Abstractions.Command; +using GFramework.Core.Abstractions.Cqrs; using GFramework.Core.Abstractions.Environment; using GFramework.Core.Abstractions.Events; using GFramework.Core.Abstractions.Ioc; @@ -13,7 +14,6 @@ using GFramework.Core.Environment; using GFramework.Core.Events; using GFramework.Core.Ioc; using GFramework.Core.Query; -using Mediator; using ICommand = GFramework.Core.Abstractions.Command.ICommand; namespace GFramework.Core.Tests.Architectures; @@ -34,6 +34,10 @@ namespace GFramework.Core.Tests.Architectures; [TestFixture] public class ArchitectureServicesTests { + private TestArchitectureContextV3? _context; + + private ArchitectureServices? _services; + [SetUp] public void SetUp() { @@ -41,9 +45,6 @@ public class ArchitectureServicesTests _context = new TestArchitectureContextV3(); } - private ArchitectureServices? _services; - private TestArchitectureContextV3? _context; - private void RegisterBuiltInServices() { _services!.ModuleManager.RegisterBuiltInModules(_services.Container); @@ -347,61 +348,59 @@ public class TestArchitectureContextV3 : IArchitectureContext { } - public ValueTask SendRequestAsync(global::GFramework.Core.Abstractions.Cqrs.IRequest request, + public ValueTask SendRequestAsync(IRequest request, CancellationToken cancellationToken = default) { throw new NotImplementedException(); } - public TResponse SendRequest(global::GFramework.Core.Abstractions.Cqrs.IRequest request) + public TResponse SendRequest(IRequest request) { throw new NotImplementedException(); } - public ValueTask SendCommandAsync( - global::GFramework.Core.Abstractions.Cqrs.Command.ICommand command, + public ValueTask SendCommandAsync(Abstractions.Cqrs.Command.ICommand command, CancellationToken cancellationToken = default) { throw new NotImplementedException(); } - public TResponse SendCommand(global::GFramework.Core.Abstractions.Cqrs.Command.ICommand command) + public TResponse SendCommand(Abstractions.Cqrs.Command.ICommand command) { throw new NotImplementedException(); } - public ValueTask SendQueryAsync( - global::GFramework.Core.Abstractions.Cqrs.Query.IQuery query, + public ValueTask SendQueryAsync(Abstractions.Cqrs.Query.IQuery query, CancellationToken cancellationToken = default) { throw new NotImplementedException(); } - public TResponse SendQuery(global::GFramework.Core.Abstractions.Cqrs.Query.IQuery query) + public TResponse SendQuery(Abstractions.Cqrs.Query.IQuery query) { throw new NotImplementedException(); } public ValueTask PublishAsync(TNotification notification, - CancellationToken cancellationToken = default) where TNotification : global::GFramework.Core.Abstractions.Cqrs.INotification + CancellationToken cancellationToken = default) where TNotification : INotification { throw new NotImplementedException(); } public IAsyncEnumerable CreateStream( - global::GFramework.Core.Abstractions.Cqrs.IStreamRequest request, + IStreamRequest request, CancellationToken cancellationToken = default) { throw new NotImplementedException(); } public ValueTask SendAsync(TCommand command, CancellationToken cancellationToken = default) - where TCommand : global::GFramework.Core.Abstractions.Cqrs.IRequest + where TCommand : IRequest { throw new NotImplementedException(); } - public ValueTask SendAsync(global::GFramework.Core.Abstractions.Cqrs.IRequest command, + public ValueTask SendAsync(IRequest command, CancellationToken cancellationToken = default) { throw new NotImplementedException(); diff --git a/GFramework.Core.Tests/Architectures/GameContextTests.cs b/GFramework.Core.Tests/Architectures/GameContextTests.cs index 6c2670bc..e11f0892 100644 --- a/GFramework.Core.Tests/Architectures/GameContextTests.cs +++ b/GFramework.Core.Tests/Architectures/GameContextTests.cs @@ -1,5 +1,6 @@ using GFramework.Core.Abstractions.Architectures; using GFramework.Core.Abstractions.Command; +using GFramework.Core.Abstractions.Cqrs; using GFramework.Core.Abstractions.Environment; using GFramework.Core.Abstractions.Events; using GFramework.Core.Abstractions.Ioc; @@ -13,7 +14,6 @@ using GFramework.Core.Environment; using GFramework.Core.Events; using GFramework.Core.Ioc; using GFramework.Core.Query; -using Mediator; using ICommand = GFramework.Core.Abstractions.Command.ICommand; namespace GFramework.Core.Tests.Architectures; @@ -394,61 +394,59 @@ public class TestArchitectureContext : IArchitectureContext { } - public ValueTask SendRequestAsync(global::GFramework.Core.Abstractions.Cqrs.IRequest request, + public ValueTask SendRequestAsync(IRequest request, CancellationToken cancellationToken = default) { throw new NotImplementedException(); } - public TResponse SendRequest(global::GFramework.Core.Abstractions.Cqrs.IRequest request) + public TResponse SendRequest(IRequest request) { throw new NotImplementedException(); } - public ValueTask SendCommandAsync( - global::GFramework.Core.Abstractions.Cqrs.Command.ICommand command, + public ValueTask SendCommandAsync(Abstractions.Cqrs.Command.ICommand command, CancellationToken cancellationToken = default) { throw new NotImplementedException(); } - public TResponse SendCommand(global::GFramework.Core.Abstractions.Cqrs.Command.ICommand command) + public TResponse SendCommand(Abstractions.Cqrs.Command.ICommand command) { throw new NotImplementedException(); } - public ValueTask SendQueryAsync( - global::GFramework.Core.Abstractions.Cqrs.Query.IQuery query, + public ValueTask SendQueryAsync(Abstractions.Cqrs.Query.IQuery query, CancellationToken cancellationToken = default) { throw new NotImplementedException(); } - public TResponse SendQuery(global::GFramework.Core.Abstractions.Cqrs.Query.IQuery query) + public TResponse SendQuery(Abstractions.Cqrs.Query.IQuery query) { throw new NotImplementedException(); } public ValueTask PublishAsync(TNotification notification, - CancellationToken cancellationToken = default) where TNotification : global::GFramework.Core.Abstractions.Cqrs.INotification + CancellationToken cancellationToken = default) where TNotification : INotification { throw new NotImplementedException(); } public IAsyncEnumerable CreateStream( - global::GFramework.Core.Abstractions.Cqrs.IStreamRequest request, + IStreamRequest request, CancellationToken cancellationToken = default) { throw new NotImplementedException(); } public ValueTask SendAsync(TCommand command, CancellationToken cancellationToken = default) - where TCommand : global::GFramework.Core.Abstractions.Cqrs.IRequest + where TCommand : IRequest { throw new NotImplementedException(); } - public ValueTask SendAsync(global::GFramework.Core.Abstractions.Cqrs.IRequest command, + public ValueTask SendAsync(IRequest command, CancellationToken cancellationToken = default) { throw new NotImplementedException(); @@ -468,7 +466,7 @@ public class TestArchitectureContext : IArchitectureContext /// 返回值类型 /// 命令对象 /// 命令执行结果 - public TResult SendCommand(Abstractions.Command.ICommand command) + public TResult SendCommand(ICommand command) { return default!; } @@ -489,7 +487,7 @@ public class TestArchitectureContext : IArchitectureContext /// 查询结果类型 /// 查询对象 /// 查询结果 - public TResult SendQuery(Abstractions.Query.IQuery query) + public TResult SendQuery(IQuery query) { return default!; } diff --git a/GFramework.Core.Tests/Coroutine/MediatorCoroutineExtensionsTests.cs b/GFramework.Core.Tests/Coroutine/MediatorCoroutineExtensionsTests.cs index eeb1493c..9dfa7b1e 100644 --- a/GFramework.Core.Tests/Coroutine/MediatorCoroutineExtensionsTests.cs +++ b/GFramework.Core.Tests/Coroutine/MediatorCoroutineExtensionsTests.cs @@ -13,68 +13,32 @@ 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 Mediator; -using Moq; namespace GFramework.Core.Tests.Coroutine; /// -/// MediatorCoroutineExtensions的单元测试类 -/// 测试Mediator模式与协程集成的扩展方法 -/// 注意:由于 Mediator 使用源生成器,本测试类主要验证接口和参数验证 +/// 的单元测试类。 +/// 验证历史命名的协程扩展已切到框架内建 CQRS runtime, +/// 并确保协程对命令调度异常的传播行为保持稳定。 /// [TestFixture] public class MediatorCoroutineExtensionsTests { - /// - /// 测试用的简单命令类 - /// - private class TestCommand : IRequest - { - public string Data { get; set; } = string.Empty; - } - - /// - /// 测试用的简单事件类 - /// - private class TestEvent - { - public string Data { get; set; } = string.Empty; - } - - /// - /// 上下文感知基类的模拟实现 - /// - private class TestContextAware : IContextAware - { - public readonly Mock _mockContext = new(); - - public IArchitectureContext GetContext() - { - return _mockContext.Object; - } - - public void SetContext(IArchitectureContext context) - { - } - } - /// /// 验证SendCommandCoroutine应该返回IEnumerator /// [Test] public void SendCommandCoroutine_Should_Return_IEnumerator_Of_YieldInstruction() { - var command = new TestCommand { Data = "Test" }; + var command = new TestCommand("Test"); var contextAware = new TestContextAware(); - // 创建 mediator 模拟 - var mediatorMock = new Mock(); - contextAware._mockContext - .Setup(ctx => ctx.GetService()) - .Returns(mediatorMock.Object); + contextAware.MockContext + .Setup(ctx => ctx.SendAsync(command, It.IsAny())) + .Returns(ValueTask.CompletedTask); var coroutine = MediatorCoroutineExtensions.SendCommandCoroutine(contextAware, command); @@ -82,23 +46,45 @@ public class MediatorCoroutineExtensionsTests } /// - /// 验证SendCommandCoroutine应该在mediator为null时抛出NullReferenceException + /// 验证 SendCommandCoroutine 在底层命令调度失败时会重新抛出原始异常。 /// [Test] - public void SendCommandCoroutine_Should_Throw_When_Mediator_Null() + public void SendCommandCoroutine_Should_Rethrow_Inner_Exception_When_Command_Fails() { - var command = new TestCommand { Data = "Test" }; + var command = new TestCommand("Test"); var contextAware = new TestContextAware(); + var expectedException = new InvalidOperationException("Command failed."); - // 设置上下文服务以返回null mediator - contextAware._mockContext - .Setup(ctx => ctx.GetService()) - .Returns((IMediator?)null); + contextAware.MockContext + .Setup(ctx => ctx.SendAsync(command, It.IsAny())) + .Returns(new ValueTask(Task.FromException(expectedException))); - // 创建协程 var coroutine = MediatorCoroutineExtensions.SendCommandCoroutine(contextAware, command); - // 调用 MoveNext 时应该抛出 NullReferenceException - Assert.Throws(() => coroutine.MoveNext()); + Assert.That(coroutine.MoveNext(), Is.True); + var exception = Assert.Throws(() => coroutine.MoveNext()); + Assert.That(exception, Is.SameAs(expectedException)); } -} \ No newline at end of file + + /// + /// 测试用的简单命令类 + /// + private sealed record TestCommand(string Data) : IRequest; + + /// + /// 上下文感知基类的模拟实现 + /// + private sealed class TestContextAware : IContextAware + { + public Mock MockContext { get; } = new(); + + public IArchitectureContext GetContext() + { + return MockContext.Object; + } + + public void SetContext(IArchitectureContext context) + { + } + } +} diff --git a/GFramework.Core.Tests/GFramework.Core.Tests.csproj b/GFramework.Core.Tests/GFramework.Core.Tests.csproj index 5e59b144..97663fe0 100644 --- a/GFramework.Core.Tests/GFramework.Core.Tests.csproj +++ b/GFramework.Core.Tests/GFramework.Core.Tests.csproj @@ -10,11 +10,6 @@ 0 - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - diff --git a/GFramework.Core/Architectures/Architecture.cs b/GFramework.Core/Architectures/Architecture.cs index 39b4fd13..ac4fa2dc 100644 --- a/GFramework.Core/Architectures/Architecture.cs +++ b/GFramework.Core/Architectures/Architecture.cs @@ -7,7 +7,6 @@ using GFramework.Core.Abstractions.Systems; using GFramework.Core.Abstractions.Utility; using GFramework.Core.Environment; using GFramework.Core.Logging; -using Microsoft.Extensions.DependencyInjection; namespace GFramework.Core.Architectures; @@ -146,8 +145,8 @@ public abstract class Architecture : IArchitecture #region Module Management /// - /// 注册中介行为管道 - /// 用于配置Mediator框架的行为拦截和处理逻辑。 + /// 注册 CQRS 请求管道行为。 + /// 历史方法名保留了 Mediator 前缀,但当前用于配置框架内建 CQRS runtime 的行为拦截和处理逻辑。 /// 可以传入开放泛型行为类型,也可以传入绑定到特定请求的封闭行为类型。 /// /// 行为类型,必须是引用类型 @@ -328,4 +327,4 @@ public abstract class Architecture : IArchitecture } #endregion -} \ No newline at end of file +} diff --git a/GFramework.Core/Architectures/ArchitectureBootstrapper.cs b/GFramework.Core/Architectures/ArchitectureBootstrapper.cs index f658329a..d022c806 100644 --- a/GFramework.Core/Architectures/ArchitectureBootstrapper.cs +++ b/GFramework.Core/Architectures/ArchitectureBootstrapper.cs @@ -2,7 +2,6 @@ using GFramework.Core.Abstractions.Architectures; using GFramework.Core.Abstractions.Environment; using GFramework.Core.Abstractions.Logging; using GFramework.Core.Cqrs.Internal; -using Microsoft.Extensions.DependencyInjection; namespace GFramework.Core.Architectures; @@ -23,7 +22,7 @@ internal sealed class ArchitectureBootstrapper( /// 因为用户初始化逻辑通常会立即访问事件总线、查询执行器或环境对象。 /// /// 调用方已经提供的上下文;如果为空则创建默认上下文。 - /// 可选的容器配置委托,用于接入 Mediator 等扩展服务。 + /// 可选的容器配置委托,用于接入额外服务或覆盖默认依赖绑定。 /// 是否以异步模式初始化服务模块。 /// 已绑定到当前架构类型的架构上下文。 public async Task PrepareForInitializationAsync( diff --git a/GFramework.Core/Architectures/ArchitectureModules.cs b/GFramework.Core/Architectures/ArchitectureModules.cs index 94acae78..d02f39e2 100644 --- a/GFramework.Core/Architectures/ArchitectureModules.cs +++ b/GFramework.Core/Architectures/ArchitectureModules.cs @@ -5,7 +5,7 @@ namespace GFramework.Core.Architectures; /// /// 架构模块管理器 -/// 负责管理架构模块的安装和中介行为注册 +/// 负责管理架构模块的安装和 CQRS 行为注册 /// internal sealed class ArchitectureModules( IArchitecture architecture, @@ -13,14 +13,14 @@ internal sealed class ArchitectureModules( ILogger logger) { /// - /// 注册中介行为管道 - /// 用于配置Mediator框架的行为拦截和处理逻辑。 + /// 注册 CQRS 请求管道行为。 + /// 历史方法名保留了 Mediator 前缀,但当前用于配置框架内建 CQRS runtime 的行为拦截和处理逻辑。 /// 支持开放泛型行为类型和针对单一请求的封闭行为类型。 /// /// 行为类型,必须是引用类型 public void RegisterMediatorBehavior() where TBehavior : class { - logger.Debug($"Registering mediator behavior: {typeof(TBehavior).Name}"); + logger.Debug($"Registering CQRS pipeline behavior: {typeof(TBehavior).Name}"); services.Container.RegisterMediatorBehavior(); } @@ -37,4 +37,4 @@ internal sealed class ArchitectureModules( logger.Info($"Module installed: {name}"); return module; } -} \ No newline at end of file +} diff --git a/GFramework.Core/Coroutine/Extensions/MediatorCoroutineExtensions.cs b/GFramework.Core/Coroutine/Extensions/MediatorCoroutineExtensions.cs index 5c301c07..42ff1ce2 100644 --- a/GFramework.Core/Coroutine/Extensions/MediatorCoroutineExtensions.cs +++ b/GFramework.Core/Coroutine/Extensions/MediatorCoroutineExtensions.cs @@ -12,21 +12,22 @@ // limitations under the License. using GFramework.Core.Abstractions.Coroutine; +using GFramework.Core.Abstractions.Cqrs; using GFramework.Core.Abstractions.Rule; -using Mediator; namespace GFramework.Core.Coroutine.Extensions; /// -/// 提供Mediator模式与协程集成的扩展方法。 -/// 包含发送命令和等待事件的协程实现。 +/// 提供 CQRS 命令与协程集成的扩展方法。 +/// 历史命名保留了 Mediator 前缀,但当前实现直接走 返回的 +/// CQRS 入口,不再依赖外部 Mediator 服务。 /// public static class MediatorCoroutineExtensions { /// - /// 以协程方式发送命令并处理可能的异常。 + /// 以协程方式发送无返回值 CQRS 命令并处理可能的异常。 /// - /// 命令的类型 + /// 命令的类型。 /// 上下文感知对象,用于获取服务 /// 要发送的命令对象 /// 发生异常时的回调处理函数 @@ -35,13 +36,12 @@ public static class MediatorCoroutineExtensions this IContextAware contextAware, TCommand command, Action? onError = null) - where TCommand : notnull + where TCommand : IRequest { - var mediator = contextAware - .GetContext() - .GetService()!; + ArgumentNullException.ThrowIfNull(contextAware); + ArgumentNullException.ThrowIfNull(command); - var task = mediator.Send(command).AsTask(); + var task = contextAware.GetContext().SendAsync(command).AsTask(); yield return task.AsCoroutineInstruction(); @@ -51,4 +51,4 @@ public static class MediatorCoroutineExtensions else throw task.Exception!.InnerException ?? task.Exception; } -} \ No newline at end of file +} diff --git a/GFramework.Core/Cqrs/Internal/CqrsHandlerRegistrar.cs b/GFramework.Core/Cqrs/Internal/CqrsHandlerRegistrar.cs index 136b76a7..957c0981 100644 --- a/GFramework.Core/Cqrs/Internal/CqrsHandlerRegistrar.cs +++ b/GFramework.Core/Cqrs/Internal/CqrsHandlerRegistrar.cs @@ -7,7 +7,7 @@ namespace GFramework.Core.Cqrs.Internal; /// /// 在架构初始化期间扫描并注册 CQRS 处理器。 -/// 首批实现采用运行时反射扫描,优先满足“无需 AddMediator 即可工作”的迁移目标。 +/// 首批实现采用运行时反射扫描,优先满足“无需额外注册步骤即可工作”的迁移目标。 /// internal static class CqrsHandlerRegistrar { diff --git a/GFramework.Core/Ioc/MicrosoftDiContainer.cs b/GFramework.Core/Ioc/MicrosoftDiContainer.cs index dec4f267..6b45a09e 100644 --- a/GFramework.Core/Ioc/MicrosoftDiContainer.cs +++ b/GFramework.Core/Ioc/MicrosoftDiContainer.cs @@ -5,7 +5,6 @@ using GFramework.Core.Abstractions.Logging; using GFramework.Core.Abstractions.Systems; using GFramework.Core.Logging; using GFramework.Core.Rule; -using Microsoft.Extensions.DependencyInjection; namespace GFramework.Core.Ioc; @@ -310,8 +309,8 @@ public class MicrosoftDiContainer(IServiceCollection? serviceCollection = null) /// - /// 注册中介行为管道 - /// 用于配置Mediator框架的行为拦截和处理逻辑。 + /// 注册 CQRS 请求管道行为。 + /// 历史方法名保留了 Mediator 前缀,但当前用于配置框架内建 CQRS runtime 的行为拦截和处理逻辑。 /// 同时支持开放泛型行为类型和已闭合的具体行为类型, /// 以兼容通用行为和针对单一请求的专用行为两种注册方式。 /// @@ -351,7 +350,7 @@ public class MicrosoftDiContainer(IServiceCollection? serviceCollection = null) } } - _logger.Debug($"Mediator behavior registered: {behaviorType.Name}"); + _logger.Debug($"CQRS pipeline behavior registered: {behaviorType.Name}"); } finally { diff --git a/docs/zh-CN/core/cqrs.md b/docs/zh-CN/core/cqrs.md index d0cf0f9e..b92566d1 100644 --- a/docs/zh-CN/core/cqrs.md +++ b/docs/zh-CN/core/cqrs.md @@ -1,21 +1,21 @@ --- -title: CQRS 与 Mediator -description: CQRS 模式通过 Mediator 实现命令查询职责分离,提供清晰的业务逻辑组织方式。 +title: CQRS +description: GFramework 内建 CQRS runtime,用统一请求分发、通知发布和流式处理组织业务逻辑。 --- -# CQRS 与 Mediator +# CQRS ## 概述 CQRS(Command Query Responsibility Segregation,命令查询职责分离)是一种架构模式,将数据的读取(Query)和修改(Command)操作分离。GFramework -通过集成 Mediator 库实现了 CQRS 模式,提供了类型安全、解耦的业务逻辑处理方式。 +当前内建自有 CQRS runtime,通过统一的请求分发器、通知发布和流式请求管道提供类型安全、解耦的业务逻辑处理方式。 通过 CQRS,你可以将复杂的业务逻辑拆分为独立的命令和查询处理器,每个处理器只负责单一职责,使代码更易于测试和维护。 **主要特性**: - 命令查询职责分离 -- 基于 Mediator 模式的解耦设计 +- 内建请求分发与解耦设计 - 支持管道行为(Behaviors) - 异步处理支持 - 与架构系统深度集成 @@ -72,7 +72,6 @@ public class GetPlayerQuery : QueryBase ```csharp using GFramework.Core.CQRS.Command; -using Mediator; // 命令处理器 public class CreatePlayerCommandHandler : AbstractCommandHandler @@ -92,19 +91,19 @@ public class CreatePlayerCommandHandler : AbstractCommandHandler // 4. 发送命令 public async Task SaveGame() { - var mediator = this.GetService(); - var command = new SaveGameCommand(new SaveGameInput { SlotId = 1, Data = currentGameData }); - await mediator.Send(command); + await this.SendAsync(command); } ``` @@ -195,21 +192,19 @@ public class GetHighScoresQueryHandler : AbstractQueryHandler> GetHighScores() { - var mediator = this.GetService(); - var query = new GetHighScoresQuery(new GetHighScoresInput { Count = 10 }); - var scores = await mediator.Send(query); + var scores = await this.SendQueryAsync(query); return scores; } ``` ### 注册处理器 -在架构中注册 Mediator 和处理器: +在架构中注册 CQRS 行为并让处理器自动扫描注册: ```csharp public class GameArchitecture : Architecture @@ -225,7 +220,7 @@ public class GameArchitecture : Architecture } ``` -`RegisterMediatorBehavior()` 同时支持两种形式: +`RegisterMediatorBehavior()` 是保留的兼容名称,当前用于注册框架内建 CQRS pipeline,支持两种形式: - 开放泛型行为,例如 `LoggingBehavior<,>`,用于匹配所有请求 - 封闭行为类型,例如某个只服务于单一请求的 `SpecialBehavior` @@ -326,7 +321,7 @@ var notification = new PlayerLevelUpNotification(new PlayerLevelUpInput NewLevel = 10 }); -await mediator.Publish(notification); +await this.PublishAsync(notification); ``` ### Pipeline Behaviors(管道行为) @@ -334,11 +329,11 @@ await mediator.Publish(notification); Behaviors 可以在处理器执行前后添加横切关注点: ```csharp -using Mediator; +using GFramework.Core.Abstractions.Cqrs; // 日志行为 public class LoggingBehavior : IPipelineBehavior - where TMessage : IMessage + where TMessage : IRequest { public async ValueTask Handle( TMessage message, @@ -358,7 +353,7 @@ public class LoggingBehavior : IPipelineBehavior : IPipelineBehavior - where TMessage : IMessage + where TMessage : IRequest { public async ValueTask Handle( TMessage message, @@ -390,7 +385,7 @@ RegisterMediatorBehavior>(); ```csharp public class ValidationBehavior : IPipelineBehavior - where TMessage : IMessage + where TMessage : IRequest { public async ValueTask Handle( TMessage message, @@ -441,7 +436,7 @@ public class GetAllPlayersStreamQueryHandler : AbstractStreamQueryHandler Handle(...) ### 问题:处理器可以调用其他处理器吗? **解答**: -可以,通过 Mediator 发送新的命令或查询: +可以,通过架构上下文继续发送新的命令或查询: ```csharp public override async ValueTask Handle(...) { - var mediator = this.GetService(); - // 调用其他命令 - await mediator.Send(new AnotherCommand(...)); + await this.SendAsync(new AnotherCommand(...)); return Unit.Value; } diff --git a/docs/zh-CN/core/index.md b/docs/zh-CN/core/index.md index 8430e58f..98455237 100644 --- a/docs/zh-CN/core/index.md +++ b/docs/zh-CN/core/index.md @@ -391,17 +391,17 @@ public class PlayerController : IController #### 5. ArchitectureModules (模块管理器) -**职责**: 管理架构模块和中介行为 +**职责**: 管理架构模块和 CQRS 管道行为 **核心功能**: - 模块安装 (IArchitectureModule) -- 中介行为注册 (Mediator Behaviors) +- CQRS 管道行为注册(历史 API 名称仍为 `RegisterMediatorBehavior`) **关键方法**: - `InstallModule()` - 安装模块 -- `RegisterMediatorBehavior()` - 注册中介行为 +- `RegisterMediatorBehavior()` - 注册 CQRS 管道行为 #### 设计优势 @@ -672,4 +672,3 @@ public interface IController : - 添加 `PhaseChanged` 事件,支持阶段监听 **向后兼容**: 所有公共 API 保持不变,现有代码无需修改。 -