mirror of
https://github.com/GeWuYou/GFramework.git
synced 2026-05-07 00:39:00 +08:00
- 调整文档真实性原则,以源码和测试为首要证据源 - 新增模块README要求,规定所有用户包必须有说明文档 - 更新仓库文档规范,要求根README与文档站点分类一致 - 添加VitePress配置文件,支持中文搜索和泛型转义 - 创建入门指南文档,说明GFramework模块组成和接入路径 - 添加快速开始教程,演示Core模块最小使用示例 - 为Core模块添加详细README文档 - 为Core.Abstractions添加契约层说明文档 - 为Core.SourceGenerators添加源码生成器文档 - 为Game模块添加运行时层详细说明文档
155 lines
6.2 KiB
Markdown
155 lines
6.2 KiB
Markdown
# GFramework.Cqrs
|
||
|
||
`GFramework.Cqrs` 是 GFramework 的默认 CQRS runtime 包。它在 `GFramework.Cqrs.Abstractions` 之上提供请求分发、通知发布、流式请求处理、处理器注册、上下文扩展方法,以及消息/处理器基类,面向直接使用 GFramework CQRS 的业务模块。
|
||
|
||
## 模块定位
|
||
|
||
- 这是 CQRS 的“默认实现层”。
|
||
- 包内同时承载运行时基础设施和面向业务代码的便捷基类。
|
||
- 它依赖 `GFramework.Cqrs.Abstractions` 与 `GFramework.Core.Abstractions`。
|
||
- 在标准 GFramework 架构启动路径中,`GFramework.Core` 的 `CqrsRuntimeModule` 会把默认 runtime、处理器注册器与注册服务自动接入容器。
|
||
|
||
如果你只需要声明跨模块共享的消息契约,而不想依赖默认 runtime,请改为引用 `GeWuYou.GFramework.Cqrs.Abstractions`。
|
||
|
||
## 包关系
|
||
|
||
推荐的依赖关系如下:
|
||
|
||
- `GeWuYou.GFramework.Cqrs.Abstractions`
|
||
- 最小 CQRS 契约层。
|
||
- `GeWuYou.GFramework.Cqrs`
|
||
- 默认 runtime 与业务侧常用基类。
|
||
- `GeWuYou.GFramework.Cqrs.SourceGenerators`
|
||
- 可选。为消费端程序集生成 `ICqrsHandlerRegistry`,运行时优先走生成注册表;缺失或不适用时,回退到反射扫描。
|
||
- `GFramework.Core`
|
||
- 架构上下文中实际调用 `ICqrsRuntime`,并在模块初始化时注册 CQRS 基础设施。
|
||
|
||
## 子系统地图
|
||
|
||
本包当前主要由以下子系统组成:
|
||
|
||
- 消息基类
|
||
- `Command/CommandBase.cs`
|
||
- `Query/QueryBase.cs`
|
||
- `Request/RequestBase.cs`
|
||
- `Notification/NotificationBase.cs`
|
||
- 处理器基类
|
||
- `Cqrs/CqrsContextAwareHandlerBase.cs`
|
||
- `Cqrs/Command/AbstractCommandHandler.cs`
|
||
- `Cqrs/Query/AbstractQueryHandler.cs`
|
||
- `Cqrs/Notification/AbstractNotificationHandler.cs`
|
||
- `Cqrs/Request/AbstractRequestHandler.cs`
|
||
- `Cqrs/Request/AbstractStreamRequestHandler.cs`
|
||
- `Cqrs/Command/AbstractStreamCommandHandler.cs`
|
||
- `Cqrs/Query/AbstractStreamQueryHandler.cs`
|
||
- 请求管道
|
||
- `Cqrs/Behaviors/LoggingBehavior.cs`
|
||
- `Cqrs/Behaviors/PerformanceBehavior.cs`
|
||
- 管道契约定义在 `GFramework.Cqrs.Abstractions` 的 `IPipelineBehavior<,>`
|
||
- 默认 runtime 与注册入口
|
||
- `CqrsRuntimeFactory.cs`
|
||
- `Internal/CqrsDispatcher.cs`
|
||
- `Internal/CqrsHandlerRegistrar.cs`
|
||
- `Internal/DefaultCqrsHandlerRegistrar.cs`
|
||
- `Internal/DefaultCqrsRegistrationService.cs`
|
||
- 生成注册表协作接口
|
||
- `ICqrsHandlerRegistry.cs`
|
||
- `CqrsHandlerRegistryAttribute.cs`
|
||
- `CqrsReflectionFallbackAttribute.cs`
|
||
- 业务侧扩展入口
|
||
- `Extensions/ContextAwareCqrsExtensions.cs`
|
||
- `Extensions/ContextAwareCqrsCommandExtensions.cs`
|
||
- `Extensions/ContextAwareCqrsQueryExtensions.cs`
|
||
|
||
## 最小接入路径
|
||
|
||
在标准 GFramework 架构中,最小接入通常是“安装包 + 定义消息 + 定义处理器 + 通过上下文发送”:
|
||
|
||
```bash
|
||
dotnet add package GeWuYou.GFramework.Cqrs
|
||
dotnet add package GeWuYou.GFramework.Cqrs.Abstractions
|
||
```
|
||
|
||
如果你希望减少处理器注册时的反射扫描,再额外安装:
|
||
|
||
```bash
|
||
dotnet add package GeWuYou.GFramework.Cqrs.SourceGenerators
|
||
```
|
||
|
||
示例:
|
||
|
||
```csharp
|
||
using GFramework.Cqrs.Command;
|
||
using GFramework.Cqrs.Cqrs.Command;
|
||
using GFramework.Cqrs.Abstractions.Cqrs.Command;
|
||
|
||
public sealed record CreatePlayerInput(string Name) : ICommandInput;
|
||
|
||
public sealed class CreatePlayerCommand : CommandBase<CreatePlayerInput, int>
|
||
{
|
||
public CreatePlayerCommand(CreatePlayerInput input) : base(input)
|
||
{
|
||
}
|
||
}
|
||
|
||
public sealed class CreatePlayerCommandHandler
|
||
: AbstractCommandHandler<CreatePlayerCommand, int>
|
||
{
|
||
public override ValueTask<int> Handle(
|
||
CreatePlayerCommand command,
|
||
CancellationToken cancellationToken)
|
||
{
|
||
var playerModel = Context.GetModel<PlayerModel>();
|
||
var playerId = playerModel.Create(command.Input.Name);
|
||
return ValueTask.FromResult(playerId);
|
||
}
|
||
}
|
||
```
|
||
|
||
在 `IContextAware` 对象内发送命令:
|
||
|
||
```csharp
|
||
using GFramework.Cqrs.Extensions;
|
||
|
||
var playerId = await this.SendAsync(new CreatePlayerCommand(new CreatePlayerInput("Alice")));
|
||
```
|
||
|
||
在 `ArchitectureContext` 上也可以直接使用统一 CQRS 入口,例如 `SendRequestAsync`、`SendQueryAsync`、`PublishAsync` 和 `CreateStream`。
|
||
|
||
## 运行时行为
|
||
|
||
- 请求分发
|
||
- `CqrsDispatcher` 按请求实际类型解析 `IRequestHandler<,>`,未找到处理器会抛出异常。
|
||
- 通知分发
|
||
- 通知会分发给所有已注册 `INotificationHandler<>`;零处理器时默认静默完成。
|
||
- 流式请求
|
||
- 通过 `IStreamRequest<TResponse>` 和 `IStreamRequestHandler<,>` 返回 `IAsyncEnumerable<TResponse>`。
|
||
- 上下文注入
|
||
- 处理器基类继承 `CqrsContextAwareHandlerBase`,runtime 会在分发前注入当前 `IArchitectureContext`。
|
||
- 如果处理器或行为需要上下文注入,而当前 `ICqrsContext` 不是 `IArchitectureContext`,默认实现会抛出异常。
|
||
- 管道行为
|
||
- 所有已注册 `IPipelineBehavior<TRequest, TResponse>` 会包裹请求处理器执行。
|
||
- 当前包内提供了 `LoggingBehavior` 和 `PerformanceBehavior` 两个可复用行为。
|
||
|
||
## 处理器注册与程序集接入
|
||
|
||
默认注册流程由 `ICqrsRegistrationService.RegisterHandlers(IEnumerable<Assembly>)` 协调,语义是:
|
||
|
||
- 同一程序集按稳定键去重,避免重复注册。
|
||
- 优先尝试消费端程序集上的 `ICqrsHandlerRegistry` 生成注册器。
|
||
- 生成注册器不可用,或声明了 `CqrsReflectionFallbackAttribute` 时,回退到反射扫描。
|
||
- 处理器以 transient 方式注册,避免上下文感知处理器在并发请求间共享可变上下文。
|
||
|
||
如果你走标准 `GFramework.Core` 架构初始化路径,这些步骤通常由框架自动完成;裸容器或测试环境则需要显式补齐 runtime 与注册入口。
|
||
|
||
## 适用边界
|
||
|
||
- 这个包是默认实现,不是“纯契约包”。
|
||
- 处理器基类依赖 runtime 在分发前注入上下文,不适合脱离 dispatcher 直接手动实例化后调用。
|
||
- README 中的消息基类和 handler 基类位于 `GFramework.Cqrs`,接口契约位于 `GFramework.Cqrs.Abstractions`;最小示例通常需要同时引入这两个命名空间层级。
|
||
|
||
## 文档入口
|
||
|
||
- 总体文档:`docs/zh-CN/core/cqrs.md`
|
||
- 契约层说明:`GFramework.Cqrs.Abstractions/README.md`
|