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

20 KiB
Raw Blame History

命令基类体系

**本文引用的文件** - [AbstractCommand.cs](file://GFramework.Core/command/AbstractCommand.cs) - [AbstractAsyncCommand.cs](file://GFramework.Core/command/AbstractAsyncCommand.cs) - [EmptyCommandInput.cs](file://GFramework.Core/command/EmptyCommandInput.cs) - [CommandBus.cs](file://GFramework.Core/command/CommandBus.cs) - [ICommand.cs](file://GFramework.Core.Abstractions/command/ICommand.cs) - [IAsyncCommand.cs](file://GFramework.Core.Abstractions/command/IAsyncCommand.cs) - [ICommandInput.cs](file://GFramework.Core.Abstractions/command/ICommandInput.cs) - [ICommandBus.cs](file://GFramework.Core.Abstractions/command/ICommandBus.cs) - [ContextAwareBase.cs](file://GFramework.Core/rule/ContextAwareBase.cs) - [README.md命令包](file://GFramework.Core/command/README.md) - [README.md抽象层](file://GFramework.Core.Abstractions/README.md) - [AbstractAsyncCommandTests.cs](file://GFramework.Core.Tests/command/AbstractAsyncCommandTests.cs) - [CommandBusTests.cs](file://GFramework.Core.Tests/command/CommandBusTests.cs)

目录

  1. 引言
  2. 项目结构
  3. 核心组件
  4. 架构总览
  5. 详细组件分析
  6. 依赖分析
  7. 性能考虑
  8. 故障排查指南
  9. 结论
  10. 附录

引言

本文件系统化梳理命令基类体系,围绕抽象命令与异步命令基类的设计理念、契约接口、输入模型、生命周期、继承扩展、参数验证与错误处理、与其他组件的集成方式,以及最佳实践与性能优化建议展开,帮助读者快速理解并高效使用命令模式在架构中的落地。

项目结构

命令相关代码位于 GFramework.Core 的 command 与 rule 子目录,契约接口位于 GFramework.Core.Abstractions 的 command 与 rule 子目录;配套测试位于 GFramework.Core.Tests 的 command 子目录README 提供使用说明与最佳实践。

graph TB
subgraph "命令实现GFramework.Core/command"
AC["AbstractCommand.cs"]
AAC["AbstractAsyncCommand.cs"]
ECI["EmptyCommandInput.cs"]
CB["CommandBus.cs"]
end
subgraph "命令契约GFramework.Core.Abstractions/command"
IC["ICommand.cs"]
IAC["IAsyncCommand.cs"]
ICI["ICommandInput.cs"]
ICB["ICommandBus.cs"]
end
subgraph "上下文基类GFramework.Core/rule"
CAB["ContextAwareBase.cs"]
end
AC --> IC
AAC --> IAC
ECI --> ICI
CB --> ICB
AC --> CAB
AAC --> CAB

图表来源

章节来源

核心组件

  • 命令接口族ICommand、ICommand、IAsyncCommand、IAsyncCommand定义执行契约与返回语义。
  • 输入模型接口ICommandInput作为命令输入的标记接口EmptyCommandInput 作为“无输入”占位实现。
  • 抽象命令基类AbstractCommand、AbstractCommand<TInput,TResult>、AbstractAsyncCommand、AbstractAsyncCommand<TInput,TResult>,提供 Execute/ExecuteAsync 的桥接与 OnExecute/OnExecuteAsync 的抽象实现。
  • 命令总线CommandBus统一发送与执行命令支持同步与异步、有返回值与无返回值。
  • 上下文感知基类ContextAwareBase为命令提供架构上下文访问能力GetModel、SendEvent 等横切能力通过扩展方法在其他模块提供)。

章节来源

架构总览

命令模式在框架中的定位:命令封装写操作,通过命令总线统一调度,命令内部通过上下文基类访问系统、模型、事件总线等能力,形成清晰的职责边界与解耦。

graph TB
Caller["调用方"] --> Bus["CommandBus"]
Bus --> Cmd["ICommand/ICommand<TResult>"]
Bus --> ACmd["IAsyncCommand/IAsyncCommand<TResult>"]
Cmd --> BaseCmd["AbstractCommand<TInput[,TResult]>"]
ACmd --> BaseACmd["AbstractAsyncCommand<TInput[,TResult]>"]
BaseCmd --> Ctx["ContextAwareBase<br/>上下文感知"]
BaseACmd --> Ctx
Ctx --> CtxGet["GetModel/GetSystem/SendEvent 等通过扩展"]

图表来源

详细组件分析

抽象命令基类(同步)

  • 设计要点
    • 封装 Execute 到 OnExecute 的桥接,保证接口契约与实现分离。
    • 泛型约束 TInput : ICommandInput强制输入模型实现标记接口。
    • 继承 ContextAwareBase天然具备上下文访问能力。
  • 生命周期
    • 创建:传入 TInput 构造。
    • 执行ICommand.Execute 调用 OnExecute(input)。
    • 返回ICommand.Execute 返回 OnExecute(input)。
    • 清理:命令对象执行后可被 GC 回收(无状态)。
  • 适用场景
    • 需要立即执行且无需返回值的写操作。
    • 需要返回结果的写操作(减少分支与歧义)。
classDiagram
class ContextAwareBase {
+SetContext(context)
+GetContext()
#OnContextReady()
}
class ICommand {
+Execute()
}
class ICommand_TResult {
+Execute() TResult
}
class ICommandInput
class AbstractCommand_TInput {
+Execute()
#OnExecute(input)
}
class AbstractCommand_TInput_TResult {
+Execute() TResult
#OnExecute(input) TResult
}
ContextAwareBase <|-- AbstractCommand_TInput
ContextAwareBase <|-- AbstractCommand_TInput_TResult
ICommand <|.. AbstractCommand_TInput
ICommand_TResult <|.. AbstractCommand_TInput_TResult
ICommandInput <.. AbstractCommand_TInput
ICommandInput <.. AbstractCommand_TInput_TResult

图表来源

章节来源

抽象命令基类(异步)

  • 设计要点
    • 封装 ExecuteAsync 到 OnExecuteAsync 的桥接,支持 Task 与 Task。
    • 同样继承 ContextAwareBase具备上下文能力。
  • 生命周期
    • 创建:传入 TInput 构造。
    • 执行IAsyncCommand.ExecuteAsync 调用 await OnExecuteAsync(input)。
    • 返回IAsyncCommand.ExecuteAsync 返回 await OnExecuteAsync(input)。
    • 清理:命令对象执行后可被 GC 回收(无状态)。
  • 适用场景
    • 需要等待 IO 或异步流程的写操作。
    • 需要返回结果的异步写操作。
classDiagram
class IAsyncCommand {
+ExecuteAsync() Task
}
class IAsyncCommand_TResult {
+ExecuteAsync() Task~TResult~
}
class AbstractAsyncCommand_TInput {
+ExecuteAsync() Task
#OnExecuteAsync(input) Task
}
class AbstractAsyncCommand_TInput_TResult {
+ExecuteAsync() Task~TResult~
#OnExecuteAsync(input) Task~TResult~
}
ContextAwareBase <|-- AbstractAsyncCommand_TInput
ContextAwareBase <|-- AbstractAsyncCommand_TInput_TResult
IAsyncCommand <|.. AbstractAsyncCommand_TInput
IAsyncCommand_TResult <|.. AbstractAsyncCommand_TInput_TResult
ICommandInput <.. AbstractAsyncCommand_TInput
ICommandInput <.. AbstractAsyncCommand_TInput_TResult

图表来源

章节来源

命令执行接口(契约)

  • ICommand/ICommand
    • Execute() 无返回值Execute() TResult 有返回值。
    • 继承 IContextAware具备上下文能力。
  • IAsyncCommand/IAsyncCommand
    • ExecuteAsync() 无返回值ExecuteAsync() TResult 有返回值。
    • 继承 IContextAware具备上下文能力。
  • ICommandBus
    • Send(ICommand)/Send(ICommand) 同步执行。
    • SendAsync(IAsyncCommand)/SendAsync(IAsyncCommand) 异步执行。
    • 对 null 参数进行显式校验,抛出 ArgumentNullException。
sequenceDiagram
participant Caller as "调用方"
participant Bus as "CommandBus"
participant Cmd as "ICommand/ICommand<TResult>"
participant ACmd as "IAsyncCommand/IAsyncCommand<TResult>"
Caller->>Bus : Send(cmd)
Bus->>Cmd : Execute()
Cmd-->>Caller : void 或 TResult
Caller->>Bus : SendAsync(asyncCmd)
Bus->>ACmd : ExecuteAsync()
ACmd-->>Caller : Task 或 Task<TResult>

图表来源

章节来源

命令输入模型设计

  • ICommandInput
    • 标记接口,不包含成员,用于约束命令输入类型。
  • EmptyCommandInput
    • 无成员的实现,用于“无输入”的命令场景。
  • 自定义输入类型
    • 定义 struct/class 实现 ICommandInput承载命令所需参数。
    • 在命令构造函数中接收并缓存,避免命令持有长期状态。
  • 最佳实践
    • 输入参数结构化、不可变init-only 属性)。
    • 仅在必要时使用 TResult避免过度设计。

章节来源

命令生命周期管理

  • 创建:命令对象实例化,注入输入参数。
  • 验证:命令内部可通过上下文访问系统/模型进行参数校验(如存在性、范围、权限等)。
  • 执行CommandBus 调用 Execute/ExecuteAsync委托至 OnExecute/OnExecuteAsync。
  • 清理:命令执行完毕即释放,适合无状态一次性操作。
  • 测试验证:单元测试覆盖了生命周期完整性、多次执行、异常传播等。
flowchart TD
Start(["创建命令"]) --> Validate["参数与前置条件验证"]
Validate --> ExecSync{"同步还是异步?"}
ExecSync --> |同步| DoSync["调用 OnExecute(input)"]
ExecSync --> |异步| DoAsync["await OnExecuteAsync(input)"]
DoSync --> Return["返回结果如有"]
DoAsync --> Return
Return --> Cleanup["命令对象可被GC回收"]

图表来源

章节来源

继承与扩展示例

  • 同步命令
    • 继承 AbstractCommand 或 AbstractCommand<TInput,TResult>,重写 OnExecute/OnExecute。
    • 示例参考测试用例中的 TestCommand、TestCommandWithResult。
  • 异步命令
    • 继承 AbstractAsyncCommand 或 AbstractAsyncCommand<TInput,TResult>,重写 OnExecuteAsync/OnExecuteAsync。
    • 示例参考测试用例中的 TestAsyncCommand、TestAsyncCommandWithResult。
  • 空输入命令
    • 使用 EmptyCommandInput 作为输入类型,简化无参命令。

章节来源

参数验证与错误处理

  • 参数验证
    • 建议在 OnExecute/OnExecuteAsync 内部进行参数合法性检查与前置条件断言。
    • 可通过上下文访问系统/模型进行业务规则校验。
  • 错误处理
    • 命令内部异常应向上抛出,交由调用方或上层中间件处理。
    • CommandBus 对传入命令进行 null 校验,避免空引用。
  • 测试覆盖
    • 单元测试验证 ExecuteAsync 异常传播、上下文设置与获取、生命周期完整性等。

章节来源

与架构其他组件的集成

  • 上下文能力
    • 命令通过 ContextAwareBase 获得上下文,结合扩展方法可访问系统、模型、事件总线等。
  • 总线协作
    • CommandBus 统一调度命令,与 QueryBus、EventBus 形成 CQRS 与事件驱动的协同。
  • 模块化
    • 命令作为写操作单元,与系统、模型、工具等模块解耦,便于测试与替换。

章节来源

依赖分析

  • 抽象命令基类依赖上下文感知基类,从而获得架构上下文能力。
  • 命令接口族依赖上下文感知能力接口,确保命令可访问系统、模型、事件等。
  • 命令总线依赖命令接口族,提供统一的发送与执行入口。
  • 输入模型接口为命令输入的契约EmptyCommandInput 作为默认实现。
graph LR
ICB["ICommandBus"] --> ICMD["ICommand / ICommand<TResult>"]
ICB --> IACMD["IAsyncCommand / IAsyncCommand<TResult>"]
ICMD --> CI["ICommandInput"]
IACMD --> CI
ACMD["AbstractCommand..."] --> ICMD
AACMD["AbstractAsyncCommand..."] --> IACMD
ACMD --> CAB["ContextAwareBase"]
AACMD --> CAB

图表来源

章节来源

性能考虑

  • 命令无状态:每次执行后即可回收,降低内存压力。
  • 避免命令嵌套:命令内尽量通过事件与查询与其他模块交互,减少耦合与栈深度。
  • 合理使用返回值:仅在确需结果时使用带返回值命令,避免不必要的开销。
  • 异步优先:涉及 IO 或长耗时操作时使用异步命令,提升吞吐。
  • 输入参数结构化:使用结构化输入减少重复校验与参数传递成本。

故障排查指南

  • 命令未执行
    • 检查是否通过 CommandBus 正确 Send/SendAsync。
    • 确认命令对象非 null。
  • 异常未被捕获
    • 命令内部异常会向上传播,确认调用方是否正确 await 或处理异常。
  • 上下文未生效
    • 确认命令已通过上下文感知机制注入架构上下文。
  • 多次执行结果不一致
    • 确保命令无状态,输入参数不可变,避免共享可变状态。

章节来源

结论

命令基类体系通过清晰的契约、简洁的抽象与统一的总线,实现了命令模式在框架中的高内聚、低耦合与可测试性。配合上下文感知能力与输入模型设计,命令能够在保证可维护性的同时,满足同步与异步、有返回值与无返回值的多样化需求。遵循最佳实践与性能建议,可在大型项目中稳定落地命令模式。

附录

  • 使用场景参考
    • 用户交互:保存游戏、加载关卡等。
    • 业务流程:战斗伤害计算、角色移动等。
  • 扩展方向
    • 命令撤销/重做(可选扩展)。
    • 命令批处理与事务化(可选扩展)。

章节来源