GeWuYou a79f02c987 docs(api): 添加 Core API 参考文档与事件系统接口文档
- 新增 Core API 参考文档,涵盖架构与模块、数据模型与系统、命令与查询等核心组件
- 添加事件系统接口详细文档,包括 IEvent、IEventBus、IUnRegister 等接口说明
- 提供完整的 API 使用示例路径、最佳实践与性能建议
- 包含架构图、依赖关系图与故障排查指南
- 添加测试用例参考与扩展方法说明
- [skip ci]
2026-01-21 23:45:10 +08:00

23 KiB
Raw Blame History

命令查询系统

**本文引用的文件** - [GFramework.Core\command\CommandBus.cs](file://GFramework.Core/command/CommandBus.cs) - [GFramework.Core\query\QueryBus.cs](file://GFramework.Core/query/QueryBus.cs) - [GFramework.Core\command\AbstractCommand.cs](file://GFramework.Core/command/AbstractCommand.cs) - [GFramework.Core\query\AbstractQuery.cs](file://GFramework.Core/query/AbstractQuery.cs) - [GFramework.Core\command\AbstractAsyncCommand.cs](file://GFramework.Core/command/AbstractAsyncCommand.cs) - [GFramework.Core\query\AbstractAsyncQuery.cs](file://GFramework.Core/query/AbstractAsyncQuery.cs) - [GFramework.Core\command\EmptyCommandInput.cs](file://GFramework.Core/command/EmptyCommandInput.cs) - [GFramework.Core\query\EmptyQueryInput.cs](file://GFramework.Core/query/EmptyQueryInput.cs) - [GFramework.Core\query\AsyncQueryBus.cs](file://GFramework.Core/query/AsyncQueryBus.cs) - [GFramework.Core.Abstractions\command\ICommand.cs](file://GFramework.Core.Abstractions/command/ICommand.cs) - [GFramework.Core.Abstractions\query\IQuery.cs](file://GFramework.Core.Abstractions/query/IQuery.cs) - [GFramework.Core.Abstractions\command\IAsyncCommand.cs](file://GFramework.Core.Abstractions/command/IAsyncCommand.cs) - [GFramework.Core.Abstractions\query\IAsyncQuery.cs](file://GFramework.Core.Abstractions/query/IAsyncQuery.cs) - [GFramework.Core.Tests\command\CommandBusTests.cs](file://GFramework.Core.Tests/command/CommandBusTests.cs) - [GFramework.Core.Tests\query\QueryBusTests.cs](file://GFramework.Core.Tests/query/QueryBusTests.cs) - [GFramework.Core.Tests\command\AbstractAsyncCommandTests.cs](file://GFramework.Core.Tests/command/AbstractAsyncCommandTests.cs) - [GFramework.Core.Tests\query\AbstractAsyncQueryTests.cs](file://GFramework.Core.Tests/query/AbstractAsyncQueryTests.cs)

目录

  1. 引言
  2. 项目结构
  3. 核心组件
  4. 架构概览
  5. 详细组件分析
  6. 依赖关系分析
  7. 性能考虑
  8. 故障排查指南
  9. 结论
  10. 附录API 参考与使用示例

引言

本技术文档围绕 GFramework 的命令查询系统,系统性阐述 CQRS命令查询职责分离模式在该框架中的实现与优势。文档重点覆盖以下方面

  • 命令总线与查询总线的设计与职责边界
  • 基于抽象基类的命令与查询实现(同步与异步)
  • 输入输出模型与类型安全设计
  • 参数验证与错误处理策略
  • 最佳实践:事务一致性与查询优化
  • 完整 API 参考与可直接定位到源码路径的使用示例

项目结构

命令查询系统位于 GFramework.Core 与 GFramework.Core.Abstractions 两个命名空间中,分别提供实现与抽象契约。核心文件组织如下:

  • 契约层Abstractions定义 ICommand/IQuery/IAsyncCommand/IAsyncQuery 等接口
  • 实现层Core提供 CommandBus/QueryBus/AsyncQueryBus 以及 AbstractCommand/AbstractQuery/AbstractAsyncCommand/AbstractAsyncQuery 等实现
  • 输入模型EmptyCommandInput/EmptyQueryInput 提供“无输入”场景的类型安全占位
  • 测试层:通过单元测试展示典型使用方式与边界条件
graph TB
subgraph "契约层"
ICMD["ICommand/ICommand<TResult>"]
IQRY["IQuery<IQuery<TResult>>"]
IACMD["IAsyncCommand/IAsyncCommand<TResult>"]
IQRYA["IAsyncQuery<TResult>"]
end
subgraph "实现层"
CB["CommandBus"]
QB["QueryBus"]
AQB["AsyncQueryBus"]
ACMD["AbstractCommand<TInput> / AbstractCommand<TInput,TResult>"]
AQRY["AbstractQuery<TInput,TResult>"]
AACMD["AbstractAsyncCommand<TInput> / AbstractAsyncCommand<TInput,TResult>"]
AQRYA["AbstractAsyncQuery<TInput,TResult>"]
ECI["EmptyCommandInput"]
EQI["EmptyQueryInput"]
end
ICMD --> CB
IQRY --> QB
IACMD --> CB
IQRYA --> QB
IQRYA --> AQB
ACMD --> CB
AQRY --> QB
AACMD --> CB
AQRYA --> QB
AQRYA --> AQB
ECI -. "实现 ICommandInput" .-> ACMD
EQI -. "实现 IQueryInput" .-> AQRY

图表来源

章节来源

核心组件

  • 命令总线CommandBus统一调度 ICommand/ICommand/IAsyncCommand/IAsyncCommand负责参数校验与执行分发
  • 查询总线QueryBus/AsyncQueryBus统一调度 IQuery/IAsyncQuery提供同步与异步查询执行入口
  • 抽象命令AbstractCommand/AbstractAsyncCommand为具体命令提供输入模型绑定、上下文感知与执行骨架
  • 抽象查询AbstractQuery/AbstractAsyncQuery为具体查询提供输入模型绑定、上下文感知与执行骨架
  • 输入模型EmptyCommandInput/EmptyQueryInput类型安全的“无输入”占位符便于零参数命令/查询的声明式建模

章节来源

架构概览

CQRS 在本框架中的体现:

  • 命令侧:写操作(变更状态),通过 CommandBus 统一调度,支持同步与异步命令
  • 查询侧:读操作(只读),通过 QueryBus/AsyncQueryBus 统一调度,支持同步与异步查询
  • 输入输出模型:所有命令/查询均通过泛型输入模型与结果类型进行强约束,避免运行期类型错误
  • 参数验证:总线在执行前对命令/查询对象进行非空校验,确保调用方契约清晰
sequenceDiagram
participant Caller as "调用方"
participant CmdBus as "CommandBus"
participant Cmd as "ICommand/ICommand<TResult>"
participant QryBus as "QueryBus/AsyncQueryBus"
participant Qry as "IQuery<TResult>/IAsyncQuery<TResult>"
Caller->>CmdBus : "Send/SendAsync(命令)"
CmdBus->>Cmd : "Execute()/ExecuteAsync()"
Cmd-->>Caller : "返回结果或完成信号"
Caller->>QryBus : "Send<TResult>(查询)"
QryBus->>Qry : "Do()/DoAsync()"
Qry-->>Caller : "返回查询结果"

图表来源

详细组件分析

命令总线CommandBus

  • 职责:接收命令对象并触发执行;提供同步与异步两类 Send/SendAsync 方法族
  • 参数验证:对传入命令进行非空检查,防止空引用传播
  • 执行路径:
    • 同步命令ICommand.Execute 或 ICommand.Execute
    • 异步命令IAsyncCommand.ExecuteAsync 或 IAsyncCommand.ExecuteAsync
  • 错误处理:空命令参数抛出参数异常;命令内部异常由命令自身处理
flowchart TD
Start(["进入 Send/SendAsync"]) --> CheckNull{"命令是否为 null?"}
CheckNull --> |是| ThrowErr["抛出参数异常"]
CheckNull --> |否| Dispatch["调用命令 Execute/ExecuteAsync"]
Dispatch --> Done(["返回结果或完成"])
ThrowErr --> Done

图表来源

章节来源

查询总线QueryBus/AsyncQueryBus

  • QueryBus面向同步查询 IQuery执行 Do 并返回结果
  • AsyncQueryBus面向异步查询 IAsyncQuery执行 DoAsync 并返回 Task
  • 共同点:均对查询对象进行非空校验,确保调用契约
sequenceDiagram
participant Caller as "调用方"
participant QB as "QueryBus"
participant Q as "IQuery<TResult>"
Caller->>QB : "Send<TResult>(query)"
QB->>QB : "校验 query 非空"
QB->>Q : "Do()"
Q-->>QB : "返回 TResult"
QB-->>Caller : "返回结果"

图表来源

章节来源

抽象命令AbstractCommand

  • 设计要点:
    • 泛型输入模型绑定TInput 必须实现 ICommandInput
    • 继承上下文感知基类,便于访问架构/系统/模型等能力
    • 派生类仅需实现 OnExecute(OnExecute) 即可完成业务逻辑
  • 类型安全:通过泛型约束确保输入与结果类型明确,避免运行期类型转换
classDiagram
class ICommandInput
class ICommand
class ICommand_TResult_
class AbstractCommand_TInput_ {
+OnExecute(input)
}
class AbstractCommand_TInput_TResult_ {
+OnExecute(input) TResult
}
ICommandInput <.. AbstractCommand_TInput_
ICommandInput <.. AbstractCommand_TInput_TResult_
ICommand <|.. AbstractCommand_TInput_
ICommand_TResult_ <|.. AbstractCommand_TInput_TResult_

图表来源

章节来源

抽象查询AbstractQuery

  • 设计要点:
    • 泛型输入模型绑定TInput 必须实现 IQueryInput
    • 继承上下文感知基类,便于访问架构/系统/模型等能力
    • 派生类仅需实现 OnDo(OnDo) 即可完成查询逻辑
  • 类型安全:通过泛型约束确保输入与结果类型明确
classDiagram
class IQueryInput
class IQuery_TResult_
class AbstractQuery_TInput_TResult_ {
+Do() TResult
+OnDo(input) TResult
}
IQueryInput <.. AbstractQuery_TInput_TResult_
IQuery_TResult_ <|.. AbstractQuery_TInput_TResult_

图表来源

章节来源

异步命令AbstractAsyncCommand

  • 支持:
    • 无返回值IAsyncCommand.ExecuteAsync
    • 有返回值IAsyncCommand.ExecuteAsync
  • 设计要点:
    • 派生类实现 OnExecuteAsync(OnExecuteAsync),可自由组合 I/O 与网络请求
    • 继承上下文感知基类,便于访问架构/系统/模型等能力
classDiagram
class IAsyncCommand
class IAsyncCommand_TResult_
class AbstractAsyncCommand_TInput_ {
+ExecuteAsync() Task
+OnExecuteAsync(input) Task
}
class AbstractAsyncCommand_TInput_TResult_ {
+ExecuteAsync() Task~TResult~
+OnExecuteAsync(input) Task~TResult~
}
IAsyncCommand <|.. AbstractAsyncCommand_TInput_
IAsyncCommand_TResult_ <|.. AbstractAsyncCommand_TInput_TResult_

图表来源

章节来源

异步查询AbstractAsyncQuery

  • 支持:
    • 有返回值IAsyncQuery.DoAsync
  • 设计要点:
    • 派生类实现 OnDoAsync(OnDoAsync),适合数据库/远程服务等异步场景
    • 继承上下文感知基类,便于访问架构/系统/模型等能力
classDiagram
class IAsyncQuery_TResult_
class AbstractAsyncQuery_TInput_TResult_ {
+DoAsync() Task~TResult~
+OnDoAsync(input) Task~TResult~
}
IAsyncQuery_TResult_ <|.. AbstractAsyncQuery_TInput_TResult_

图表来源

章节来源

输入输出模型与类型安全

  • EmptyCommandInput/EmptyQueryInput实现对应输入接口作为“无输入”场景的类型安全占位
  • 类型安全保证:
    • 命令/查询通过泛型输入与结果类型约束,避免运行期类型错误
    • 总线在执行前进行非空校验,确保调用契约清晰

章节来源

依赖关系分析

  • 契约与实现解耦Abstractions 定义接口Core 提供默认实现,便于替换与扩展
  • 总线与命令/查询:总线仅依赖接口契约,不关心具体实现,降低耦合度
  • 上下文感知:抽象基类统一继承上下文感知基类,便于访问架构能力
graph LR
ICMD["ICommand/ICommand<TResult>"] --> CB["CommandBus"]
IACMD["IAsyncCommand/IAsyncCommand<TResult>"] --> CB
IQRY["IQuery<TResult>"] --> QB["QueryBus"]
IQRYA["IAsyncQuery<TResult>"] --> QB
IQRYA --> AQB["AsyncQueryBus"]
ACMD["AbstractCommand*"] --> CB
AQRY["AbstractQuery*"] --> QB
AACMD["AbstractAsyncCommand*"] --> CB
AQRYA["AbstractAsyncQuery*"] --> QB
AQRYA --> AQB

图表来源

章节来源

性能考虑

  • 异步优先:对于 I/O 密集或外部服务交互,优先使用 AbstractAsyncCommand/AbstractAsyncQuery 与 AsyncQueryBus避免阻塞主线程
  • 结果复用:对昂贵查询结果进行缓存(建议结合上层缓存策略),减少重复计算
  • 输入最小化:尽量使用 EmptyCommandInput/EmptyQueryInput 进行零参数场景,减少序列化与传输开销
  • 事务边界:命令执行应尽量保持短事务,必要时将长流程拆分为多个命令,配合事件驱动实现最终一致

故障排查指南

  • 空命令/查询异常:若出现参数异常,检查调用处是否传入 null或确认总线调用链是否正确
  • 异常传播:命令/查询内部抛出的异常会沿调用栈传播,需在命令/查询实现中妥善处理并记录日志
  • 上下文缺失:若命令/查询依赖上下文能力,请确保在执行前设置上下文

章节来源

结论

GFramework 的命令查询系统以 CQRS 为核心思想,通过总线与抽象基类实现清晰的职责分离与类型安全。命令侧强调写操作的一致性与可追踪性,查询侧强调读操作的可扩展与可优化。结合异步能力与输入模型占位,开发者可在保证类型安全的同时快速构建高性能的命令查询应用。

附录API 参考与使用示例

  • 契约接口
    • 命令接口ICommand、ICommand
    • 异步命令接口IAsyncCommand、IAsyncCommand
    • 查询接口IQuery
    • 异步查询接口IAsyncQuery
  • 实现类
    • 命令总线CommandBus
    • 查询总线QueryBus、AsyncQueryBus
    • 抽象命令AbstractCommand、AbstractCommand<TInput,TResult>、AbstractAsyncCommand、AbstractAsyncCommand<TInput,TResult>
    • 抽象查询AbstractQuery<TInput,TResult>、AbstractAsyncQuery<TInput,TResult>
    • 输入模型EmptyCommandInput、EmptyQueryInput
  • 使用示例(路径定位)

章节来源