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

查询基类体系

**本文引用的文件** - [AbstractQuery.cs](file://GFramework.Core/query/AbstractQuery.cs) - [AbstractAsyncQuery.cs](file://GFramework.Core/query/AbstractAsyncQuery.cs) - [EmptyQueryInput.cs](file://GFramework.Core/query/EmptyQueryInput.cs) - [QueryBus.cs](file://GFramework.Core/query/QueryBus.cs) - [AsyncQueryBus.cs](file://GFramework.Core/query/AsyncQueryBus.cs) - [IQuery.cs](file://GFramework.Core.Abstractions/query/IQuery.cs) - [IAsyncQuery.cs](file://GFramework.Core.Abstractions/query/IAsyncQuery.cs) - [IQueryBus.cs](file://GFramework.Core.Abstractions/query/IQueryBus.cs) - [IAsyncQueryBus.cs](file://GFramework.Core.Abstractions/query/IAsyncQueryBus.cs) - [IQueryInput.cs](file://GFramework.Core.Abstractions/query/IQueryInput.cs) - [ContextAwareBase.cs](file://GFramework.Core/rule/ContextAwareBase.cs) - [IContextAware.cs](file://GFramework.Core.Abstractions/rule/IContextAware.cs) - [QueryBusTests.cs](file://GFramework.Core.Tests/query/QueryBusTests.cs) - [AsyncQueryBusTests.cs](file://GFramework.Core.Tests/query/AsyncQueryBusTests.cs) - [AbstractAsyncQueryTests.cs](file://GFramework.Core.Tests/query/AbstractAsyncQueryTests.cs)

目录

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

引言

本文件系统化梳理查询基类体系,围绕以下目标展开:深入解释同步与异步查询基类的设计理念与实现细节;阐明查询执行接口的契约与实现要求;说明查询输入模型的设计模式(含 EmptyQueryInput 的使用场景与自定义输入类型的实现方法);解释查询生命周期(创建、验证、执行、结果处理);给出继承与扩展示例;介绍参数验证机制与结果映射策略;说明与架构其他组件的集成方式,并总结最佳实践、性能优化与缓存策略。

项目结构

查询体系位于 GFramework.Core 与 GFramework.Core.Abstractions 两个工程中,分别提供具体实现与抽象契约。核心文件分布如下:

  • 抽象层契约IQuery、IAsyncQuery、IQueryBus、IAsyncQueryBus、IQueryInput、IContextAware
  • 具体实现AbstractQuery、AbstractAsyncQuery、EmptyQueryInput、QueryBus、AsyncQueryBus
  • 上下文感知ContextAwareBase
  • 测试QueryBusTests、AsyncQueryBusTests、AbstractAsyncQueryTests
graph TB
subgraph "抽象契约"
IQ["IQuery<TResult>"]
IAQ["IAsyncQuery<TResult>"]
IQB["IQueryBus"]
IAQB["IAsyncQueryBus"]
IQIn["IQueryInput"]
ICA["IContextAware"]
end
subgraph "具体实现"
AQ["AbstractQuery<TInput,TResult>"]
AAQ["AbstractAsyncQuery<TInput,TResult>"]
EQI["EmptyQueryInput"]
QB["QueryBus"]
AQB["AsyncQueryBus"]
CAB["ContextAwareBase"]
end
IQ -.实现.-> AQ
IAQ -.实现.-> AAQ
IQB -.调度.-> QB
IAQB -.调度.-> AQB
IQIn -.约束.-> AQ
IQIn -.约束.-> AAQ
ICA -.实现.-> CAB
CAB -.继承.-> AQ
CAB -.继承.-> AAQ
EQI -.实现.-> IQIn

图表来源

章节来源

核心组件

  • 同步查询基类 AbstractQuery<TInput, TResult>
    • 设计要点:通过泛型约束 TInput 实现 IQueryInput封装 Do() 调用 OnDo(input),子类仅需实现 OnDo。
    • 生命周期:创建(构造注入 input、验证由调用方保证 input 有效、执行Do -> OnDo、结果返回。
  • 异步查询基类 AbstractAsyncQuery<TInput, TResult>
    • 设计要点:与同步版本一致,但 DoAsync -> OnDoAsync 返回 Task适合 IO 密集或需要取消的场景。
  • 查询输入模型 EmptyQueryInput
    • 使用场景:无需任何输入参数的查询;作为占位符实现 IQueryInput。
    • 自定义输入类型:实现 IQueryInput 并在查询类中声明对应泛型 TInput。
  • 查询总线 QueryBus / AsyncQueryBus
    • 职责:接收 IQuery/IAsyncQuery 对象,进行参数校验(非空),转发到查询对象执行并返回结果。
    • 同步总线Send(IQuery) -> query.Do()
    • 异步总线SendAsync(IAsyncQuery) -> query.DoAsync()

章节来源

架构概览

查询体系采用“接口契约 + 抽象基类 + 总线分发”的分层设计,确保:

  • 契约清晰IQuery/IAsyncQuery 定义最小可执行能力
  • 执行解耦AbstractQuery/AbstractAsyncQuery 将执行细节留给子类
  • 分发统一QueryBus/AsyncQueryBus 提供集中式入口与基础验证
  • 上下文感知ContextAwareBase 为查询提供架构上下文访问能力
sequenceDiagram
participant Client as "调用方"
participant Bus as "QueryBus/AsyncQueryBus"
participant Q as "IQuery/IAsyncQuery 实现"
participant Impl as "AbstractQuery/AbstractAsyncQuery 子类"
Client->>Bus : "Send/SendAsync(query)"
Bus->>Bus : "参数校验(非空)"
alt 同步
Bus->>Q : "Do()"
Q->>Impl : "OnDo(input)"
Impl-->>Q : "返回 TResult"
Q-->>Bus : "返回 TResult"
Bus-->>Client : "返回 TResult"
else 异步
Bus->>Q : "DoAsync()"
Q->>Impl : "OnDoAsync(input)"
Impl-->>Q : "返回 Task<TResult>"
Q-->>Bus : "返回 Task<TResult>"
Bus-->>Client : "返回 Task<TResult>"
end

图表来源

详细组件分析

接口契约与实现要求

  • IQuery
    • 方法Do() -> TResult
    • 实现要求:提供确定性、无副作用或受控副作用的纯查询逻辑
  • IAsyncQuery
    • 方法DoAsync() -> Task
    • 实现要求:避免阻塞,支持取消与超时;错误应直接传播
  • IQueryBus / IAsyncQueryBus
    • 方法Send/SendAsync 接收 IQuery/IAsyncQuery返回 TResult/Task
    • 实现要求:必须进行非空校验;其余交由查询对象处理

章节来源

抽象基类设计与实现细节

  • AbstractQuery<TInput, TResult>
    • 构造:接收 TInput input实现 IQueryInput
    • Do() -> OnDo(input);子类仅实现 OnDo
    • 适用场景CPU 密集或内存内数据查询
  • AbstractAsyncQuery<TInput, TResult>
    • 构造:接收 TInput input实现 IQueryInput
    • DoAsync() -> OnDoAsync(input);子类仅实现 OnDoAsync
    • 适用场景IO 操作、网络请求、可取消任务
classDiagram
class IContextAware {
+SetContext(context)
+GetContext() IArchitectureContext
}
class ContextAwareBase {
-Context : IArchitectureContext?
+SetContext(context)
+GetContext() IArchitectureContext
#OnContextReady()
}
class IQuery~TResult~ {
+Do() TResult
}
class AbstractQuery~TInput,TResult~ {
+Do() TResult
#OnDo(input : TInput) TResult
}
class IAsyncQuery~TResult~ {
+DoAsync() Task~TResult~
}
class AbstractAsyncQuery~TInput,TResult~ {
+DoAsync() Task~TResult~
#OnDoAsync(input : TInput) Task~TResult~
}
IContextAware <|.. ContextAwareBase
ContextAwareBase <|-- AbstractQuery~TInput,TResult~
ContextAwareBase <|-- AbstractAsyncQuery~TInput,TResult~
IQuery~TResult~ <|.. AbstractQuery~TInput,TResult~
IAsyncQuery~TResult~ <|.. AbstractAsyncQuery~TInput,TResult~

图表来源

章节来源

查询输入模型设计模式

  • EmptyQueryInput
    • 作用:实现 IQueryInput作为“无输入”查询的占位符
    • 使用建议:当查询完全依赖上下文或全局状态时,避免冗余输入参数
  • 自定义输入类型
    • 步骤:实现 IQueryInput在查询类中声明为泛型 TInput在构造函数中注入
    • 注意:输入应尽量轻量、不可变、可序列化(便于日志与调试)

章节来源

查询生命周期管理

  • 创建:构造 AbstractQuery/AbstractAsyncQuery 时注入 TInput
  • 验证:总线层对 query 进行非空校验;输入参数的有效性由子类 OnDo/OnDoAsync 内部处理
  • 执行:同步 Do() 或异步 DoAsync();内部委托给 OnDo/OnDoAsync
  • 结果处理:返回 TResult 或 Task异常直接传播
flowchart TD
Start(["开始"]) --> NewQuery["创建查询实例<br/>注入输入参数"]
NewQuery --> Validate["总线层参数校验(非空)"]
Validate --> Exec{"同步还是异步?"}
Exec --> |同步| Do["调用 Do()"]
Exec --> |异步| DoAsync["调用 DoAsync()"]
Do --> OnDo["调用 OnDo(input)"]
DoAsync --> OnDoAsync["调用 OnDoAsync(input)"]
OnDo --> Result["返回 TResult"]
OnDoAsync --> TaskRes["返回 Task<TResult>"]
Result --> End(["结束"])
TaskRes --> End

图表来源

章节来源

继承与扩展示例

  • 同步查询示例(来自测试)
    • 输入TestQueryInput实现 IQueryInput
    • 查询TestQuery继承 AbstractQuery<TestQueryInput, int>
    • 实现:重写 OnDo返回 input.Value * 2
  • 异步查询示例(来自测试)
    • 输入TestAsyncQueryInput实现 IQueryInput
    • 查询TestAsyncQuery继承 AbstractAsyncQuery<TestAsyncQueryInput, int>
    • 实现:重写 OnDoAsync返回 Task.FromResult(input.Value * 2)
  • 空输入查询
    • 使用 EmptyQueryInput 作为输入,查询内部从上下文或其他来源取值

章节来源

参数验证机制与结果映射策略

  • 参数验证
    • 总线层对查询对象进行非空校验ArgumentNullException
    • 输入层TInput 必须实现 IQueryInput具体业务参数有效性由 OnDo/OnDoAsync 内部校验
  • 结果映射
    • 直接映射OnDo/OnDoAsync 返回 TResult
    • 复杂对象:可返回自定义 DTO 或实体;测试中展示了复杂对象与字符串、布尔等类型的返回
    • 异常传播:查询内部抛出的异常由总线层直接传播,便于上层统一处理

章节来源

与架构其他组件的集成

  • 上下文感知
    • AbstractQuery/AbstractAsyncQuery 继承 ContextAwareBase可访问 IArchitectureContext
    • 通过 IContextAware.SetContext/GetContext 注入与获取上下文
  • 与其他总线的协作
    • 查询总线与命令总线、事件总线协同工作,遵循统一的“输入-执行-输出”范式
  • 可测试性
    • 测试覆盖了 Do/DoAsync 调用链、异常传播、多实例独立性、不同返回类型等

章节来源

依赖关系分析

  • 抽象层依赖
    • IQuery/IAsyncQuery 依赖 IContextAware同步查询基类间接依赖
    • IQueryBus/IAsyncQueryBus 依赖各自对应的接口
  • 实现层依赖
    • AbstractQuery/AbstractAsyncQuery 依赖 ContextAwareBase 与 IQueryInput
    • QueryBus/AsyncQueryBus 依赖各自接口与查询对象
  • 测试依赖
    • 测试类依赖具体查询实现与输入类型,验证契约与行为
graph LR
ICA["IContextAware"] --> CAB["ContextAwareBase"]
CAB --> AQ["AbstractQuery"]
CAB --> AAQ["AbstractAsyncQuery"]
IQIn["IQueryInput"] --> AQ
IQIn --> AAQ
IQ["IQuery<TResult>"] --> AQ
IAQ["IAsyncQuery<TResult>"] --> AAQ
IQB["IQueryBus"] --> QB["QueryBus"]
IAQB["IAsyncQueryBus"] --> AQB["AsyncQueryBus"]

图表来源

章节来源

性能考虑

  • 选择同步或异步
    • CPU 密集且快速:优先 AbstractQuery减少异步开销
    • IO 密集或可取消:优先 AbstractAsyncQuery提升吞吐与响应性
  • 结果类型
    • 尽量使用轻量、不可变的 DTO避免大对象频繁拷贝
  • 总线层校验
    • 利用总线层的非空校验,减少重复校验成本
  • 缓存策略(建议)
    • 对于稳定查询,可在查询内部或上层总线层引入只读缓存(基于输入哈希键)
    • 注意缓存失效与一致性,结合事件驱动更新
  • 并发与隔离
    • 多实例独立性已在测试中验证,避免共享可变状态

故障排查指南

  • 常见问题
    • 传入空查询对象:总线层会抛出参数异常;请检查构造与注入
    • 查询内部异常:异常会直接传播至上层;请在上层捕获并记录
    • 上下文未设置:若查询依赖上下文,请确保通过 SetContext 注入
  • 定位手段
    • 单元测试覆盖了异常路径与多实例行为,可参考测试用例定位问题
    • 在 OnDo/OnDoAsync 中增加必要的日志与断言

章节来源

结论

查询基类体系通过清晰的契约、可复用的抽象与统一的总线分发提供了高内聚、低耦合的查询执行框架。同步与异步基类分别适配不同场景EmptyQueryInput 与自定义输入类型满足多样化的输入需求。配合上下文感知与严格的生命周期管理,查询体系易于扩展、测试与维护。建议在实际项目中遵循本文最佳实践,结合业务场景选择合适的执行模型与缓存策略。

附录

  • 最佳实践
    • 明确输入模型:尽量使用 IQueryInput 的强类型输入,避免魔法参数
    • 控制副作用:查询应尽量无副作用或受控;必要时通过命令总线分离
    • 异常处理:在总线层统一捕获与记录,查询内部抛出语义化异常
    • 可测试性:为查询编写单元测试,覆盖正常路径、异常路径与边界条件
  • 性能优化
    • 选择合适基类:根据任务特性选择同步或异步
    • 结果建模:使用不可变、轻量的数据结构
    • 缓存:对稳定查询引入只读缓存,注意一致性
  • 集成建议
    • 与事件总线、命令总线协同,形成完整的 CQRS/事件驱动架构
    • 通过上下文注入访问服务与配置,避免硬编码