Merge pull request #271 from GeWuYou/docs/sdk-update-documentation

Docs/sdk update documentation
This commit is contained in:
gewuyou 2026-04-23 09:22:23 +08:00 committed by GitHub
commit 3f95843d59
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
37 changed files with 1789 additions and 1934 deletions

View File

@ -12,7 +12,9 @@ Shortcut: `$gframework-pr-review`
## Workflow
1. Read `AGENTS.md` before deciding how to validate or fix anything.
2. Resolve the current branch with Windows Git from WSL, following the repository worktree rule.
2. Resolve the current branch following the repository worktree rule:
- prefer Linux `git` with explicit `--git-dir` / `--work-tree` binding in WSL worktrees
- only fall back to `git.exe` when that executable is available and actually runnable in the current session
3. Run `scripts/fetch_current_pr_review.py` to:
- locate the PR for the current branch through the GitHub PR API
- fetch PR metadata, issue comments, reviews, and review comments through the GitHub API
@ -31,20 +33,20 @@ Shortcut: `$gframework-pr-review`
## Commands
- Default:
- `python3 .codex/skills/gframework-pr-review/scripts/fetch_current_pr_review.py`
- `python3 .agents/skills/gframework-pr-review/scripts/fetch_current_pr_review.py`
- Recommended machine-readable workflow:
- `python3 .codex/skills/gframework-pr-review/scripts/fetch_current_pr_review.py --pr 265 --json-output /tmp/pr265-review.json`
- `python3 .agents/skills/gframework-pr-review/scripts/fetch_current_pr_review.py --pr 265 --json-output /tmp/pr265-review.json`
- `jq '.coderabbit_review.outside_diff_comments' /tmp/pr265-review.json`
- Force a PR number:
- `python3 .codex/skills/gframework-pr-review/scripts/fetch_current_pr_review.py --pr 253`
- `python3 .agents/skills/gframework-pr-review/scripts/fetch_current_pr_review.py --pr 253`
- Machine-readable output:
- `python3 .codex/skills/gframework-pr-review/scripts/fetch_current_pr_review.py --format json`
- `python3 .agents/skills/gframework-pr-review/scripts/fetch_current_pr_review.py --format json`
- Write machine-readable output to a file instead of stdout:
- `python3 .codex/skills/gframework-pr-review/scripts/fetch_current_pr_review.py --pr 253 --format json --json-output /tmp/pr253-review.json`
- `python3 .agents/skills/gframework-pr-review/scripts/fetch_current_pr_review.py --pr 253 --format json --json-output /tmp/pr253-review.json`
- Inspect only a high-signal section:
- `python3 .codex/skills/gframework-pr-review/scripts/fetch_current_pr_review.py --pr 253 --section outside-diff`
- `python3 .agents/skills/gframework-pr-review/scripts/fetch_current_pr_review.py --pr 253 --section outside-diff`
- Narrow text output to one path fragment:
- `python3 .codex/skills/gframework-pr-review/scripts/fetch_current_pr_review.py --pr 253 --section outside-diff --path GFramework.Core/Events/Event.cs`
- `python3 .agents/skills/gframework-pr-review/scripts/fetch_current_pr_review.py --pr 253 --section outside-diff --path GFramework.Core/Events/Event.cs`
## Output Expectations
@ -67,6 +69,7 @@ The script should produce:
- If the current branch has no matching public PR, report that clearly instead of guessing.
- If GitHub access fails because of proxy configuration, rerun the fetch with proxy variables removed.
- If the current WSL session resolves `git.exe` but cannot execute it cleanly, keep using the explicit Linux worktree binding instead of retrying Windows Git.
- Prefer GitHub API results over PR HTML. The PR HTML page is now a fallback/debugging source, not the primary source of truth.
- If the summary block and the latest head review threads disagree, trust the latest unresolved head-review threads and treat older summary findings as stale until re-verified locally.
- Do not assume every AI reviewer behaves like CodeRabbit. `greptile-apps[bot]` findings may exist only as latest-head review threads, without CodeRabbit-style issue comments or folded review-body sections.

View File

@ -21,8 +21,11 @@ from typing import Any
OWNER = "GeWuYou"
REPO = "GFramework"
WORKTREE_ROOT_DIRECTORY_NAME = "GFramework-WorkTree"
DEFAULT_WINDOWS_GIT = "/mnt/d/Tool/Development Tools/Git/cmd/git.exe"
GIT_ENVIRONMENT_KEY = "GFRAMEWORK_WINDOWS_GIT"
GIT_DIR_ENVIRONMENT_KEY = "GFRAMEWORK_GIT_DIR"
WORK_TREE_ENVIRONMENT_KEY = "GFRAMEWORK_WORK_TREE"
USER_AGENT = "codex-gframework-pr-review"
CODERABBIT_LOGIN = "coderabbitai[bot]"
GREPTILE_LOGIN = "greptile-apps[bot]"
@ -83,6 +86,43 @@ def resolve_git_command() -> str:
raise RuntimeError(f"No usable git executable found. Set {GIT_ENVIRONMENT_KEY} to override it.")
def find_repository_root(start_path: Path) -> Path | None:
"""Locate the repository root by walking parent directories for repo markers."""
for candidate in (start_path, *start_path.parents):
if (candidate / "AGENTS.md").exists() and (candidate / ".ai/environment/tools.ai.yaml").exists():
return candidate
return None
def resolve_worktree_git_dir(repository_root: Path) -> Path | None:
"""Resolve the main-repository worktree gitdir for this WSL worktree layout."""
if repository_root.parent.name != WORKTREE_ROOT_DIRECTORY_NAME:
return None
primary_repository_root = repository_root.parent.parent / REPO
candidate_git_dir = primary_repository_root / ".git" / "worktrees" / repository_root.name
return candidate_git_dir if candidate_git_dir.exists() else None
def resolve_git_invocation() -> list[str]:
"""Resolve the git command arguments, preferring explicit WSL worktree binding."""
configured_git_dir = os.environ.get(GIT_DIR_ENVIRONMENT_KEY)
configured_work_tree = os.environ.get(WORK_TREE_ENVIRONMENT_KEY)
linux_git = shutil.which("git")
if configured_git_dir and configured_work_tree and linux_git:
return [linux_git, f"--git-dir={configured_git_dir}", f"--work-tree={configured_work_tree}"]
repository_root = find_repository_root(Path.cwd())
if repository_root is not None and linux_git:
worktree_git_dir = resolve_worktree_git_dir(repository_root)
if worktree_git_dir is not None:
return [linux_git, f"--git-dir={worktree_git_dir}", f"--work-tree={repository_root}"]
return [resolve_git_command()]
def resolve_request_timeout_seconds() -> int:
"""Return the GitHub request timeout in seconds."""
configured_timeout = os.environ.get(REQUEST_TIMEOUT_ENVIRONMENT_KEY)
@ -113,7 +153,7 @@ def run_command(args: list[str]) -> str:
def get_current_branch() -> str:
"""Return the current git branch name."""
return run_command([resolve_git_command(), "rev-parse", "--abbrev-ref", "HEAD"])
return run_command([*resolve_git_invocation(), "rev-parse", "--abbrev-ref", "HEAD"])
def open_url(url: str, accept: str) -> tuple[str, Any]:

View File

@ -10,14 +10,21 @@ All AI agents and contributors must follow these rules when writing, reviewing,
- Use `@.ai/environment/tools.raw.yaml` only when you need the full collected facts behind the AI-facing hints.
- Prefer the project-relevant tools listed there instead of assuming every installed system tool is fair game.
- If the real environment differs from the inventory, use the project-relevant installed tool and report the mismatch.
- When working in WSL against this repository's Windows-backed worktree, prefer Windows Git from WSL (for example
`git.exe`) instead of the Linux `git` binary.
- If a Git command in WSL fails with a worktree-style “not a git repository” path translation error, rerun it with the
Windows Git executable and treat that as the repository-default Git path for the rest of the task.
- If the shell does not currently resolve `git.exe` to the host Windows Git installation, prepend that installation's
command directory to `PATH` and reset shell command hashing for the current session before continuing.
- After resolving the host Windows Git path, prefer an explicit session-local binding for subsequent commands so the
shell does not fall back to Linux `/usr/bin/git` later in the same WSL session.
- When working in WSL against this repository's Windows-backed worktree, first prefer Linux `git` with an explicit
`--git-dir=<repo>/.git/worktrees/<worktree-name>` and `--work-tree=<worktree-root>` binding for every repository
command. Treat that explicit binding as higher priority than `git.exe`, because it avoids WSL worktree path
translation mistakes and still works in sessions where Windows `.exe` execution is unavailable.
- If a plain Linux `git` command in WSL fails with a worktree-style “not a git repository” path translation error,
rerun it with the explicit `--git-dir` / `--work-tree` binding before trying `git.exe`.
- Only prefer Windows Git from WSL (for example `git.exe`) when that executable is both resolvable and executable in the
current session, and when the explicit Linux `git` binding is unavailable or has already failed.
- If the shell resolves `git.exe` but the current WSL session cannot execute it cleanly (for example `Exec format
error`), keep using the explicit Linux `git` binding for the rest of the task instead of retrying Windows Git.
- If the shell does not currently resolve `git.exe` to the host Windows Git installation and you still need Windows Git
as a fallback, prepend that installation's command directory to `PATH` and reset shell command hashing for the
current session before continuing.
- After resolving either strategy, prefer a session-local binding or command wrapper for subsequent Git commands so the
shell does not silently fall back to the wrong repository context later in the same WSL session.
## Git Workflow Rules

View File

@ -2,6 +2,8 @@
`GFramework.Core.Abstractions` 承载 `Core` 运行时对应的接口、枚举和值对象,用来定义跨模块协作边界。
它只描述契约,不提供默认的架构、事件、状态、资源或 IoC 实现;这些实现都在 `GFramework.Core` 中。
## 什么时候单独依赖它
- 你在做插件、适配层或扩展包,只想依赖契约,不想把完整运行时拉进来
@ -20,23 +22,34 @@
## 契约地图
| 目录 | 作用 |
| 目录 | 作用 |
| --- | --- |
| `Architectures/` | `IArchitecture`、模块、阶段监听与服务管理契约 |
| `Command/` / `Query/` | 旧版命令与查询执行器接口 |
| `Controller/` | `IController` |
| `Events/` | 事件契约、解绑接口与传播上下文 |
| `Model/` / `Systems/` / `Utility/` | 核心组件接口 |
| `State/` / `StateManagement/` | 状态机、Store、reducer、selector 契约 |
| `Property/` | `IBindableProperty` 与只读属性接口 |
| `Resource/` | 资源管理与释放策略契约 |
| `Localization/` | 本地化表、格式化与异常类型 |
| `Logging/` | logger、log entry、factory 相关契约 |
| `Ioc/` | `IIocContainer` |
| `Lifecycle/` | 初始化 / 销毁生命周期契约 |
| `Coroutine/` | 时间源、yield 指令与协程状态枚举 |
| `Pause/` | 暂停栈、token 与状态事件 |
| `Storage/` / `Serializer/` / `Versioning/` | 通用存储、序列化与版本化契约 |
| `Architectures/` `Lifecycle/` `Registries/` | `IArchitecture`、上下文、模块、服务模块、阶段监听、注册表基类与生命周期契约 |
| `Bases/` `Controller/` `Model/` `Systems/` `Utility/` `Rule/` | 组件角色接口、优先级 / key 值对象、上下文感知约束与扩展边界 |
| `Command/` `Query/` `Cqrs/` | 旧版命令 / 查询执行器接口,以及 `ICqrsRuntime` 这类新请求模型接线契约 |
| `Events/` `Property/` `State/` `StateManagement/` | 事件总线、解绑对象、可绑定属性、状态机、Store / reducer / middleware 契约 |
| `Coroutine/` `Time/` `Pause/` `Concurrency/` | 协程状态、时间源、暂停栈、键控异步锁和统计对象 |
| `Resource/` `Pool/` `Logging/` `Localization/` | 资源句柄、对象池、日志、日志工厂、本地化表与格式化契约 |
| `Configuration/` `Environment/` | 配置管理器、环境对象与运行时环境访问契约 |
| `Data/` `Serializer/` `Storage/` `Versioning/` | 数据装载、序列化、存储与版本化契约 |
| `Enums/` `Properties/` | 架构阶段枚举,以及架构 / logger 相关属性键 |
## XML 覆盖基线
截至 `2026-04-22`,已按顶层目录对 `GFramework.Core.Abstractions` 的公开 / 内部类型声明做过一轮轻量盘点;当前契约目录族的类型声明都已带
XML 注释。这里记录的是类型族级基线,成员级契约细节仍需要在后续波次继续审计。
| 类型族 | 基线状态 | 代表类型 |
| --- | --- | --- |
| `Architectures/` `Lifecycle/` `Registries/` | `20/20` 个类型声明已带 XML 注释 | `IArchitecture``IArchitectureContext``IServiceModule``KeyValueRegistryBase<TKey, TValue>` |
| `Command/` `Query/` `Cqrs/` | `10/10` 个类型声明已带 XML 注释 | `ICommandExecutor``IAsyncQueryExecutor``ICqrsRuntime` |
| `Events/` `Property/` `State/` `StateManagement/` | `25/25` 个类型声明已带 XML 注释 | `IEventBus``IBindableProperty<T>``IStateMachine``IStore<TState>` |
| `Coroutine/` `Time/` `Pause/` `Concurrency/` | `17/17` 个类型声明已带 XML 注释 | `IYieldInstruction``ITimeProvider``IPauseStackManager``IAsyncKeyLockManager` |
| `Resource/` `Pool/` `Logging/` `Localization/` | `27/27` 个类型声明已带 XML 注释 | `IResourceManager``IObjectPoolSystem``ILogger``ILocalizationManager` |
| `Configuration/` `Environment/` `Data/` `Serializer/` `Storage/` `Versioning/` | `7/7` 个类型声明已带 XML 注释 | `IConfigurationManager``IEnvironment``ILoadableFrom<T>``ISerializer``IStorage` |
| `Bases/` `Controller/` `Model/` `Systems/` `Utility/` `Rule/` `Enums/` `Properties/` | `19/19` 个类型声明已带 XML 注释 | `IPrioritized``IController``IModel``ISystem``IContextUtility``ArchitecturePhase` |
完整 inventory 与阅读顺序见 `docs/zh-CN/abstractions/core-abstractions.md`
## 采用建议
@ -44,8 +57,18 @@
- 若你只需要对接口编程,可以仅引用本包,再在应用层自行提供实现
- 若你在写上层模块,优先把公共契约放在 `*.Abstractions`,实现放在对应 runtime 包
## 重点 XML 关注点
如果你在做契约审计、模块拆分或测试替身,优先看这些类型族的 XML 文档:
- 架构与模块入口:`IArchitecture``IArchitectureContext``IServiceModule`
- 运行时基础设施:`IIocContainer``ILogger``IResourceManager``IConfigurationManager`
- 状态与并发能力:`IStateMachine``IStore``IAsyncKeyLockManager``ITimeProvider`
- 迁移与组合边界:`ICommandExecutor``IQueryExecutor``ICqrsRuntime`
## 对应文档
- 抽象接口栏目:[`../docs/zh-CN/abstractions/index.md`](../docs/zh-CN/abstractions/index.md)
- Core 抽象页:[`../docs/zh-CN/abstractions/core-abstractions.md`](../docs/zh-CN/abstractions/core-abstractions.md)
- Core 运行时入口:[`../GFramework.Core/README.md`](../GFramework.Core/README.md)
- API 参考入口:[`../docs/zh-CN/api-reference/index.md`](../docs/zh-CN/api-reference/index.md)

View File

@ -10,9 +10,10 @@
- `Architecture``ArchitectureContext`
- `Model` / `System` / `Utility` 运行时
- 旧版 `Command` / `Query` 执行器
- 事件、属性、状态机、状态管理
- 资源、日志、协程、并发、环境与本地化
- 旧版 `Command` / `Query` 执行器,以及与新版 `CQRS` runtime 的接线入口
- 事件、属性、状态机、状态管理、规则与上下文扩展
- 资源、对象池、日志、协程、并发、环境、配置与本地化
- 服务模块管理、时间提供器与默认的 IoC 容器适配
它不负责:
@ -37,6 +38,7 @@
| 目录 | 作用 |
| --- | --- |
| `Architectures/` | 架构入口、上下文、生命周期、模块安装与组件注册 |
| `Services/` | 服务模块注册、生命周期协调与模块管理 |
| `Command/` | 旧版命令执行器与同步 / 异步命令基类 |
| `Query/` | 旧版查询执行器与同步 / 异步查询基类 |
| `Events/` | 事件总线、事件作用域、统计与过滤 |
@ -44,15 +46,37 @@
| `State/` | 状态机与状态切换事件 |
| `StateManagement/` | Store、selector、middleware 与状态诊断 |
| `Coroutine/` | 协程调度、快照、统计与优先级 |
| `Time/` | 默认时间提供器与协程时间源 |
| `Resource/` | 资源缓存、句柄和释放策略 |
| `Pool/` | 对象池系统与常用池化辅助实现 |
| `Logging/` | logger、factory、配置与组合日志器 |
| `Ioc/` | 基于 `Microsoft.Extensions.DependencyInjection` 的容器适配 |
| `Concurrency/` | 键控异步锁与统计 |
| `Configuration/` | 配置管理器与配置监听解绑对象 |
| `Environment/` | 运行环境对象与上下文环境扩展 |
| `Pause/` | 暂停栈和暂停范围 |
| `Localization/` | 本地化表与格式化入口 |
| `Rule/` | `ContextAwareBase` 等上下文感知基类 |
| `Functional/` | `Option``Result` 等轻量函数式工具 |
| `Extensions/` | 上下文与集合等扩展方法 |
## XML 覆盖基线
截至 `2026-04-22`,已按顶层目录对 `GFramework.Core` 的公开 / 内部类型声明做过一轮轻量盘点;当前主目录族的类型声明都已带
XML 注释。这里先保留阅读基线,成员级 ``<param>`` / ``<returns>`` / 生命周期语义审计仍属于后续治理项。
| 类型族 | 基线状态 | 代表类型 |
| --- | --- | --- |
| `Architectures/` `Services/` | `22/22` 个类型声明已带 XML 注释 | `Architecture``ArchitectureContext``ArchitectureLifecycle``ServiceModuleManager` |
| `Command/` `Query/` | `15/15` 个类型声明已带 XML 注释 | `CommandExecutor``AsyncQueryExecutor``AbstractCommand<TInput>``AbstractQuery<TResult>` |
| `Events/` `Property/` `State/` `StateManagement/` | `29/29` 个类型声明已带 XML 注释 | `EventBus``BindableProperty<T>``StateMachine``Store<TState>` |
| `Coroutine/` `Time/` `Pause/` `Concurrency/` | `43/43` 个类型声明已带 XML 注释 | `CoroutineScheduler``CoroutineHandle``PauseStackManager``AsyncKeyLockManager` |
| `Resource/` `Pool/` | `8/8` 个类型声明已带 XML 注释 | `ResourceManager``AutoReleaseStrategy``AbstractObjectPoolSystem<TKey, TObject>` |
| `Logging/` `Localization/` `Configuration/` `Environment/` `Ioc/` | `31/31` 个类型声明已带 XML 注释 | `ConsoleLogger``LocalizationManager``ConfigurationManager``DefaultEnvironment``MicrosoftDiContainer` |
| `Model/` `Systems/` `Utility/` `Rule/` `Extensions/` `Functional/` | `34/34` 个类型声明已带 XML 注释 | `AbstractModel``AbstractSystem``NumericDisplayFormatter``ContextAwareBase``Result<T>` |
完整的模块化阅读顺序和 inventory 说明见 `docs/zh-CN/core/index.md`
## 最小接入路径
```bash
@ -80,5 +104,7 @@ dotnet add package GeWuYou.GFramework.Core.Abstractions
## 对应文档
- Core 栏目:[`../docs/zh-CN/core/index.md`](../docs/zh-CN/core/index.md)
- Core 抽象层:[`../docs/zh-CN/abstractions/core-abstractions.md`](../docs/zh-CN/abstractions/core-abstractions.md)
- API 参考入口:[`../docs/zh-CN/api-reference/index.md`](../docs/zh-CN/api-reference/index.md)
- CQRS[`../docs/zh-CN/core/cqrs.md`](../docs/zh-CN/core/cqrs.md)
- 入门指南:[`../docs/zh-CN/getting-started/index.md`](../docs/zh-CN/getting-started/index.md)

View File

@ -1144,6 +1144,13 @@ public sealed class CqrsHandlerRegistryGenerator : IIncrementalGenerator
string HandlerInterfaceDisplayName,
string HandlerInterfaceLogName);
/// <summary>
/// 标记某条 handler 注册语句在生成阶段采用的表达策略。
/// </summary>
/// <remarks>
/// 该枚举只服务于输出排序与代码分支选择,用来保证生成注册器在“直接注册”
/// “反射实现类型查找”和“精确运行时类型解析”之间保持稳定顺序。
/// </remarks>
private enum OrderedRegistrationKind
{
Direct,
@ -1151,6 +1158,14 @@ public sealed class CqrsHandlerRegistryGenerator : IIncrementalGenerator
PreciseReflected
}
/// <summary>
/// 描述生成注册器中某个运行时类型引用的构造方式。
/// </summary>
/// <remarks>
/// 某些 handler 服务类型可以直接以 <c>typeof(...)</c> 输出,某些则需要在运行时补充
/// 反射查找、数组/指针封装或泛型实参重建。该记录把这些差异收敛为统一的递归结构,
/// 供源码输出阶段生成稳定的类型解析语句。
/// </remarks>
private sealed record RuntimeTypeReferenceSpec(
string? TypeDisplayName,
string? ReflectionTypeMetadataName,
@ -1161,18 +1176,27 @@ public sealed class CqrsHandlerRegistryGenerator : IIncrementalGenerator
RuntimeTypeReferenceSpec? GenericTypeDefinitionReference,
ImmutableArray<RuntimeTypeReferenceSpec> GenericTypeArguments)
{
/// <summary>
/// 创建一个可直接通过 <c>typeof(...)</c> 表达的类型引用。
/// </summary>
public static RuntimeTypeReferenceSpec FromDirectReference(string typeDisplayName)
{
return new RuntimeTypeReferenceSpec(typeDisplayName, null, null, null, 0, null, null,
ImmutableArray<RuntimeTypeReferenceSpec>.Empty);
}
/// <summary>
/// 创建一个需要从当前消费端程序集反射解析的类型引用。
/// </summary>
public static RuntimeTypeReferenceSpec FromReflectionLookup(string reflectionTypeMetadataName)
{
return new RuntimeTypeReferenceSpec(null, reflectionTypeMetadataName, null, null, 0, null, null,
ImmutableArray<RuntimeTypeReferenceSpec>.Empty);
}
/// <summary>
/// 创建一个需要从被引用程序集反射解析的类型引用。
/// </summary>
public static RuntimeTypeReferenceSpec FromExternalReflectionLookup(
string reflectionAssemblyName,
string reflectionTypeMetadataName)
@ -1182,18 +1206,27 @@ public sealed class CqrsHandlerRegistryGenerator : IIncrementalGenerator
ImmutableArray<RuntimeTypeReferenceSpec>.Empty);
}
/// <summary>
/// 创建一个数组类型引用。
/// </summary>
public static RuntimeTypeReferenceSpec FromArray(RuntimeTypeReferenceSpec elementTypeReference, int arrayRank)
{
return new RuntimeTypeReferenceSpec(null, null, null, elementTypeReference, arrayRank, null, null,
ImmutableArray<RuntimeTypeReferenceSpec>.Empty);
}
/// <summary>
/// 创建一个指针类型引用。
/// </summary>
public static RuntimeTypeReferenceSpec FromPointer(RuntimeTypeReferenceSpec pointedAtTypeReference)
{
return new RuntimeTypeReferenceSpec(null, null, null, null, 0, pointedAtTypeReference, null,
ImmutableArray<RuntimeTypeReferenceSpec>.Empty);
}
/// <summary>
/// 创建一个封闭泛型类型引用。
/// </summary>
public static RuntimeTypeReferenceSpec FromConstructedGeneric(
RuntimeTypeReferenceSpec genericTypeDefinitionReference,
ImmutableArray<RuntimeTypeReferenceSpec> genericTypeArguments)

View File

@ -651,32 +651,70 @@ internal static class CqrsHandlerRegistrar
}
}
/// <summary>
/// 描述某个程序集在生成注册器之后仍需运行时补扫的 handler 元数据。
/// </summary>
/// <remarks>
/// 该对象把“是否存在精确 fallback 类型列表”与“是否只能回退到整程序集扫描”收敛为同一份内部状态,
/// 供注册流水线后续阶段统一判断。
/// </remarks>
private sealed class ReflectionFallbackMetadata(IReadOnlyList<Type> types)
{
/// <summary>
/// 获取需要通过运行时反射补充注册的 handler 类型集合。
/// </summary>
public IReadOnlyList<Type> Types { get; } = types ?? throw new ArgumentNullException(nameof(types));
/// <summary>
/// 获取当前是否持有精确的 fallback 类型清单。
/// </summary>
public bool HasExplicitTypes => Types.Count > 0;
}
/// <summary>
/// 描述单个程序集在注册阶段提取到的 generated registry 与 reflection fallback 元数据。
/// </summary>
private sealed class AssemblyRegistrationMetadata(
IReadOnlyList<Type> registryTypes,
ReflectionFallbackMetadata? reflectionFallbackMetadata)
{
/// <summary>
/// 获取程序集上声明的 generated registry 类型集合。
/// </summary>
public IReadOnlyList<Type> RegistryTypes { get; } =
registryTypes ?? throw new ArgumentNullException(nameof(registryTypes));
/// <summary>
/// 获取该程序集是否还要求运行时补充 reflection fallback。
/// </summary>
public ReflectionFallbackMetadata? ReflectionFallbackMetadata { get; } = reflectionFallbackMetadata;
}
/// <summary>
/// 缓存 generated registry 激活所需的类型判定结果与工厂委托。
/// </summary>
/// <remarks>
/// 该缓存把“是否实现契约”“是否为抽象类型”“是否已构建激活委托”封装为不可变快照,
/// 避免对同一 registry 类型重复执行反射分析。
/// </remarks>
private sealed class RegistryActivationMetadata(
bool implementsRegistryContract,
bool isAbstract,
Func<ICqrsHandlerRegistry>? factory)
{
/// <summary>
/// 获取目标类型是否实现了 <see cref="ICqrsHandlerRegistry" />。
/// </summary>
public bool ImplementsRegistryContract { get; } = implementsRegistryContract;
/// <summary>
/// 获取目标类型是否为抽象类型。
/// </summary>
public bool IsAbstract { get; } = isAbstract;
/// <summary>
/// 获取可用于实例化 registry 的工厂委托。
/// </summary>
public Func<ICqrsHandlerRegistry>? Factory { get; } = factory;
}
}

View File

@ -0,0 +1,103 @@
# GFramework.Ecs.Arch.Abstractions
`GFramework.Ecs.Arch.Abstractions` 承载 Arch ECS 集成层的最小契约,用来让共享业务层、宿主循环或扩展模块在不依赖
`GFramework.Ecs.Arch` 默认实现的前提下,仍然可以约定 ECS 模块边界。
如果你需要的是 `UseArch(...)` 扩展、`ArchSystemAdapter<T>` 基类、`World` 注册和默认模块实现,请改为依赖
`GFramework.Ecs.Arch`
## 包定位
- 这是 `Ecs.Arch` 的契约层,不是默认实现层。
- 适合让上层模块只面向 `IArchEcsModule``IArchSystemAdapter<T>``ArchOptions` 编程。
- 常见场景:
- 共享宿主循环只依赖更新契约,不直接引用 Arch runtime 实现
- 多程序集之间需要共享 ECS 配置对象或接口边界
- 测试替身、编辑器工具或外部适配层希望复用契约,但自行决定底层实现
## 与相邻包的关系
- `GFramework.Core.Abstractions`
- 本包直接依赖它,并复用 `IServiceModule``ISystem` 等基础契约。
- `GFramework.Ecs.Arch.Abstractions`
- 只定义 Arch ECS 集成相关的最小契约和配置对象。
- `GFramework.Ecs.Arch`
- 本包的默认实现层。
- 负责 `UseArch(...)` 扩展、默认模块注册、Arch `World` 装配,以及系统适配器基类。
## 契约地图
| 文件 | 作用 |
| --- | --- |
| `IArchEcsModule.cs` | ECS 模块服务契约,负责统一驱动系统更新 |
| `IArchSystemAdapter.cs` | 让 ECS 系统适配到 GFramework `ISystem` 生命周期的接口 |
| `ArchOptions.cs` | `WorldCapacity``EnableStatistics``Priority` 等配置对象 |
## XML 阅读基线
下表记录当前契约包的类型声明级 XML 基线,方便把 README、站内抽象页与源码阅读顺序对齐。
| 类型族 | 代表类型 | XML 状态 | 阅读重点 |
| --- | --- | --- | --- |
| 模块契约 | `IArchEcsModule` | 已覆盖 | 宿主循环如何统一驱动 ECS 更新 |
| 系统桥接契约 | `IArchSystemAdapter<T>` | 已覆盖 | 外部模块怎样只依赖更新接口而不绑定默认实现 |
| 配置对象 | `ArchOptions` | 已覆盖 | 跨程序集共享 ECS 配置边界 |
## 最小接入路径
### 1. 只想约定宿主循环与 ECS 模块边界
```csharp
using GFramework.Ecs.Arch.Abstractions;
public sealed class EcsUpdateLoop
{
private readonly IArchEcsModule _ecsModule;
public EcsUpdateLoop(IArchEcsModule ecsModule)
{
_ecsModule = ecsModule;
}
public void Tick(float deltaTime)
{
_ecsModule.Update(deltaTime);
}
}
```
### 2. 只想共享配置对象
```csharp
using GFramework.Ecs.Arch.Abstractions;
var options = new ArchOptions
{
WorldCapacity = 2048,
EnableStatistics = true,
Priority = 40
};
```
### 3. 什么时候要升级到 `GFramework.Ecs.Arch`
一旦你需要下面任一项,就不该只停留在本包:
- `UseArch(...)` 或其他 runtime 装配入口
- `ArchSystemAdapter<T>` 等默认基类
- Arch `World` 的创建、注册和查询能力
- 与 `GFramework` 架构生命周期绑定的默认模块实现
## 边界说明
- 本包不提供 Arch `World` 的默认构造与注册逻辑。
- 本包不提供系统基类、扩展方法或默认服务实现。
- 它回答的是“外部模块怎样与 Arch ECS 集成层约定边界”不是“Arch ECS 默认怎么接入到项目里”。
## 对应文档入口
- 抽象接口总览:[`../docs/zh-CN/abstractions/index.md`](../docs/zh-CN/abstractions/index.md)
- Ecs.Arch 抽象层说明:[`../docs/zh-CN/abstractions/ecs-arch-abstractions.md`](../docs/zh-CN/abstractions/ecs-arch-abstractions.md)
- ECS 模块入口:[`../docs/zh-CN/ecs/index.md`](../docs/zh-CN/ecs/index.md)
- Arch ECS 集成:[`../docs/zh-CN/ecs/arch.md`](../docs/zh-CN/ecs/arch.md)
- 运行时实现入口:[`../GFramework.Ecs.Arch/README.md`](../GFramework.Ecs.Arch/README.md)

View File

@ -1,16 +1,30 @@
# GFramework.Ecs.Arch
GFramework 的 Arch ECS 集成包,提供开箱即用的 ECSEntity Component System支持
`GFramework.Ecs.Arch``GFramework` 当前 Arch ECS family 的默认运行时实现包
## 特性
它负责把 Arch `World`、GFramework 的服务模块生命周期,以及 `ArchSystemAdapter<T>` 系统桥接到同一条采用路径中。
如果你需要的只是共享契约,请改为依赖 `GFramework.Ecs.Arch.Abstractions`
- 🎯 **显式集成** - 符合 .NET 生态习惯的显式注册方式
- 🔌 **零依赖** - 不使用时Core 包无 Arch 依赖
- 🎯 **类型安全** - 完整的类型系统和编译时检查
- ⚡ **高性能** - 基于 Arch ECS 的高性能实现
- 🔧 **易扩展** - 简单的系统适配器模式
## 包定位
## 快速开始
- 这是运行时实现层,不是纯契约层。
- 适合需要 `UseArch(...)``World` 自动注册、默认模块生命周期和系统桥接基类的项目。
- 常见场景:
- 在架构实例上显式接入 Arch ECS
- 让 `World` 由默认模块创建并放入容器
- 让 ECS 系统复用 `ArchSystemAdapter<float>` 生命周期桥接
- 通过 `IArchEcsModule.Update(deltaTime)` 统一驱动 ECS 帧更新
## 与相邻包的关系
- `GFramework.Core`
- 提供架构、容器、生命周期和系统注册基础设施。
- `GFramework.Ecs.Arch.Abstractions`
- 提供 `IArchEcsModule``IArchSystemAdapter<T>` 和契约层 `ArchOptions`
- `GFramework.Ecs.Arch`
- 提供 `UseArch(...)`、默认 `ArchEcsModule``World` 注册,以及系统适配器基类与示例类型。
## 最小接入路径
### 1. 安装包
@ -18,53 +32,43 @@ GFramework 的 Arch ECS 集成包,提供开箱即用的 ECSEntity Component
dotnet add package GeWuYou.GFramework.Ecs.Arch
```
### 2. 注册 ECS 模块
### 2. 在 `Initialize()` 之前显式接入 Arch runtime
按当前实现,`UseArch(...)` 会把 `ArchEcsModule` 提前登记到 `ArchitectureModuleRegistry`,因此调用时机应早于
`Initialize()`
```csharp
// 在架构初始化时添加 Arch ECS 支持
var architecture = new GameArchitecture(config)
.UseArch(); // 添加 ECS 支持
using GFramework.Core.Architectures;
using GFramework.Ecs.Arch.Extensions;
architecture.Initialize();
```
public sealed class GameArchitecture : Architecture
{
public GameArchitecture() : base(new ArchitectureConfiguration())
{
}
### 3. 带配置的注册
protected override void OnInitialize()
{
RegisterSystem<MovementSystem>();
}
}
```csharp
var architecture = new GameArchitecture(config)
var architecture = new GameArchitecture()
.UseArch(options =>
{
options.WorldCapacity = 2000;
options.EnableStatistics = true;
options.WorldCapacity = 2048;
options.Priority = 50;
});
architecture.Initialize();
```
```csharp
using System.Runtime.InteropServices;
[StructLayout(LayoutKind.Sequential)]
public struct Position(float x, float y)
{
public float X { get; set; } = x;
public float Y { get; set; } = y;
}
[StructLayout(LayoutKind.Sequential)]
public struct Velocity(float x, float y)
{
public float X { get; set; } = x;
public float Y { get; set; } = y;
}
```
### 5. 创建系统
### 3. 编写并注册系统
```csharp
using Arch.Core;
using GFramework.Ecs.Arch;
using GFramework.Ecs.Arch.Components;
public sealed class MovementSystem : ArchSystemAdapter<float>
{
@ -78,115 +82,57 @@ public sealed class MovementSystem : ArchSystemAdapter<float>
protected override void OnUpdate(in float deltaTime)
{
World.Query(in _query, (ref Position pos, ref Velocity vel) =>
var frameDelta = deltaTime;
World.Query(in _query, (ref Position position, ref Velocity velocity) =>
{
pos.X += vel.X * deltaTime;
pos.Y += vel.Y * deltaTime;
position.X += velocity.X * frameDelta;
position.Y += velocity.Y * frameDelta;
});
}
}
```
### 6. 注册系统
### 4. 初始化后获取 `World` 与 ECS 模块
```csharp
public class MyArchitecture : Architecture
{
protected override void OnRegisterSystem(IIocContainer container)
{
container.Register<MovementSystem>();
}
}
using Arch.Core;
using GFramework.Ecs.Arch.Abstractions;
var world = architecture.Context.GetService<World>();
var ecsModule = architecture.Context.GetService<IArchEcsModule>();
```
### 7. 创建实体
### 5. 由宿主循环驱动更新
```csharp
var world = this.GetService<World>();
var entity = world.Create(
new Position(0, 0),
new Velocity(1, 1)
);
```
### 8. 更新系统
```csharp
var ecsModule = this.GetService<IArchEcsModule>();
ecsModule.Update(deltaTime);
```
## 配置选项
## 运行时职责地图
### 代码配置
| 文件 | 作用 |
| --- | --- |
| `Extensions/ArchExtensions.cs` | 通过 `UseArch(...)` 把默认模块注册到 `ArchitectureModuleRegistry` |
| `ArchEcsModule.cs` | 创建并注册 `World`,按优先级收集 `ArchSystemAdapter<float>`,负责初始化、销毁和逐帧更新 |
| `ArchSystemAdapter.cs` | 把 GFramework 系统生命周期桥接到 Arch `ISystem<T>` 生命周期 |
| `ArchOptions.cs` | 承载 `WorldCapacity``EnableStatistics``Priority` 这组运行时配置 |
| `Components/*.cs``Systems/*.cs` | 提供最小组件与系统示例,帮助对照查询写法和更新模式 |
```csharp
var architecture = new GameArchitecture(config)
.UseArch(options =>
{
options.WorldCapacity = 2000;
options.EnableStatistics = true;
options.Priority = 50;
});
```
## XML 阅读基线
### 配置说明
下表记录当前模块 README 与源码可对照的类型声明级 XML 基线。
- `WorldCapacity` - World 初始容量默认1000
- `EnableStatistics` - 是否启用统计信息默认false
- `Priority` - 模块优先级默认50
| 类型族 | 代表类型 | XML 状态 | 阅读重点 |
| --- | --- | --- | --- |
| 装配入口 | `ArchExtensions` | 已覆盖 | `UseArch(...)` 的时机与返回值 |
| 运行时模块 | `ArchEcsModule` | 已覆盖 | `World` 注册、系统排序、销毁顺序 |
| 系统桥接层 | `ArchSystemAdapter<T>` | 已覆盖 | `OnArchInitialize``OnUpdate``OnArchDispose` |
| 示例类型 | `Position``Velocity``MovementSystem` | 已覆盖 | 组件布局、查询写法、最小示例 |
## 架构说明
## 对应文档入口
### 显式注册模式
本包采用 .NET 生态标准的显式注册模式,基于架构实例:
**优点:**
- ✅ 符合 .NET 生态习惯
- ✅ 显式、可控
- ✅ 易于测试和调试
- ✅ 支持配置
- ✅ 支持链式调用
- ✅ 避免"魔法"行为
**使用方式:**
```csharp
// 在架构初始化时添加
var architecture = new GameArchitecture(config)
.UseArch(); // 显式注册
architecture.Initialize();
```
详见:[INTEGRATION_PATTERN.md](INTEGRATION_PATTERN.md)
### 系统适配器
`ArchSystemAdapter<T>` 桥接 Arch.System.ISystem<T> 到 GFramework 架构:
- 自动获取 World 实例
- 集成到框架生命周期
- 支持上下文感知Context-Aware
### 生命周期
1. **注册阶段** - 模块自动注册到架构
2. **初始化阶段** - 创建 World初始化系统
3. **运行阶段** - 每帧调用 Update
4. **销毁阶段** - 清理资源,销毁 World
## 示例
完整示例请参考 `GFramework.Ecs.Arch.Tests` 项目。
## 依赖
- GFramework.Core >= 1.0.0
- Arch >= 2.1.0
- Arch.System >= 1.1.0
## 许可证
MIT License
- ECS 总览:[`../docs/zh-CN/ecs/index.md`](../docs/zh-CN/ecs/index.md)
- Arch ECS 集成:[`../docs/zh-CN/ecs/arch.md`](../docs/zh-CN/ecs/arch.md)
- 抽象契约页:[`../docs/zh-CN/abstractions/ecs-arch-abstractions.md`](../docs/zh-CN/abstractions/ecs-arch-abstractions.md)
- 统一 API / XML 导航:[`../docs/zh-CN/api-reference/index.md`](../docs/zh-CN/api-reference/index.md)

View File

@ -131,6 +131,20 @@ Scene 与 UI 路由共享这套基础约定。
- `Enums/`
- UI/Scene 转场、UI 层级、输入动作、存储类型等公共枚举
## XML 覆盖基线
下面这份 inventory 记录的是 `2026-04-23``GFramework.Game.Abstractions` 做的一轮轻量 XML 盘点结果:只统计公开 /
内部类型声明是否带 XML 注释,用来建立契约层阅读入口;成员级参数、返回值、异常和生命周期说明仍需要在后续 API 波次继续细化。
| 契约族 | 基线状态 | 代表类型 | 阅读重点 |
| --- | --- | --- | --- |
| `Config/` | `7/7` 个类型声明已带 XML 注释 | `IConfigLoader``IConfigRegistry``IConfigTable<TKey, TValue>``ConfigLoadException` | 看配置表注册、读取约定和失败诊断模型 |
| `Data/` | `14/14` 个类型声明已带 XML 注释 | `IDataRepository``ISettingsDataRepository``ISaveRepository<TSaveData>``DataRepositoryOptions` | 看业务数据、设置持久化、槽位存档和版本迁移契约 |
| `Setting/` | `12/12` 个类型声明已带 XML 注释 | `ISettingsData``ISettingsModel``ISettingsSystem``LocalizationSettings` | 看设置数据、应用语义、迁移接口和内置设置对象 |
| `Scene/` | `14/14` 个类型声明已带 XML 注释 | `IScene``ISceneRouter``ISceneFactory``SceneTransitionEvent` | 看场景行为、路由、工厂 / root 边界与转场事件模型 |
| `UI/` | `19/19` 个类型声明已带 XML 注释 | `IUiPage``IUiRouter``IUiFactory``UiInteractionProfile``UiTransitionHandlerOptions` | 看页面栈、层级 UI、输入动作与 UI 转场契约 |
| `Routing/` `Storage/` `Asset/` `Enums/` | `13/13` 个类型声明已带 XML 注释 | `IRoute``IRouteContext``IFileStorage``IAssetRegistry<T>``UiLayer``SceneTransitionType` | 看公共路由上下文、存储角色、资源注册表与跨层共享枚举 |
## 最小接入路径
### 1. 只想在公共业务层声明游戏对象

View File

@ -44,6 +44,15 @@ GameProject/
默认情况下,打包产物会通过 `targets``schemas/**/*.schema.json` 纳入 `AdditionalFiles`
## XML 覆盖基线
下面这份 inventory 记录的是 `2026-04-23``GFramework.Game.SourceGenerators` 做的一轮轻量 XML 盘点结果:只统计公开类型声明是否带 XML 注释,用来建立生成器入口;具体诊断消息、生成输出和兼容性语义仍需要回到源码与测试继续核对。
| 类型族 | 基线状态 | 代表类型 | 阅读重点 |
| --- | --- | --- | --- |
| `Config/` | `1/1` 个类型声明已带 XML 注释 | `SchemaConfigGenerator` | 看 schema 到配置类型 / 表包装 / 注册辅助代码的生成入口 |
| `Diagnostics/` | `1/1` 个类型声明已带 XML 注释 | `ConfigSchemaDiagnostics` | 看生成器会抛出的诊断类别与失败边界 |
## 最小接入路径
```xml

View File

@ -169,6 +169,19 @@
这两部分一般被上层子系统消费,不是多数项目的第一接入点。
## XML 覆盖基线
下面这份 inventory 记录的是 `2026-04-23``GFramework.Game` 做的一轮轻量 XML 盘点结果:只统计公开 /
内部类型声明是否带 XML 注释,用来建立运行时阅读入口;成员级参数、返回值、异常和生命周期说明仍需要在后续 API 波次继续细化。
| 子系统 | 基线状态 | 代表类型 | 阅读重点 |
| --- | --- | --- | --- |
| `Config/` | `26/26` 个类型声明已带 XML 注释 | `YamlConfigLoader``ConfigRegistry``GameConfigBootstrap``YamlConfigSchemaValidator` | 看 YAML 加载、schema 校验、模块接入与热重载边界 |
| `Data/` `Storage/` `Serializer/` | `8/8` 个类型声明已带 XML 注释 | `DataRepository``SaveRepository<TSaveData>``UnifiedSettingsDataRepository``FileStorage``JsonSerializer` | 看持久化布局、槽位存档、统一设置文件和底层序列化 / 存储实现 |
| `Setting/` | `9/9` 个类型声明已带 XML 注释 | `SettingsModel<TRepository>``SettingsSystem``SettingsAppliedEvent<T>` | 看初始化、应用、保存、重置等设置生命周期编排 |
| `Scene/` `UI/` `Routing/` | `10/10` 个类型声明已带 XML 注释 | `SceneRouterBase``UiRouterBase``SceneTransitionPipeline``UiTransitionPipeline``RouterBase<TRoute, TContext>` | 看路由基类、转换处理器和项目层需要自己提供的 factory / root 边界 |
| `Extensions/` `Internal/` `State/` | `3/3` 个类型声明已带 XML 注释 | `DataLocationExtensions``VersionedMigrationRunner``GameStateMachineSystem` | 看辅助扩展、内部迁移执行逻辑和游戏态状态机封装 |
## 最小接入路径
下面按最常见的四种接入目标给出最短路径。

View File

@ -27,11 +27,22 @@
| `GFramework.Game.Abstractions` | `Game` 对应的契约层 | [README](GFramework.Game.Abstractions/README.md) |
| `GFramework.Godot` | Godot 集成层负责把框架能力接入节点、场景、UI、设置与存储 | [README](GFramework.Godot/README.md) |
| `GFramework.Ecs.Arch` | Arch ECS 集成 | [README](GFramework.Ecs.Arch/README.md) |
| `GFramework.Ecs.Arch.Abstractions` | Arch ECS 集成对应的契约层,适合共享宿主循环与 ECS 模块边界 | [README](GFramework.Ecs.Arch.Abstractions/README.md) |
| `GFramework.Core.SourceGenerators` | Core 侧通用源码生成器与分析器 | [README](GFramework.Core.SourceGenerators/README.md) |
| `GFramework.Game.SourceGenerators` | 游戏内容配置 schema 生成器 | [README](GFramework.Game.SourceGenerators/README.md) |
| `GFramework.Cqrs.SourceGenerators` | CQRS handler registry 生成器 | [README](GFramework.Cqrs.SourceGenerators/README.md) |
| `GFramework.Godot.SourceGenerators` | Godot 场景专用源码生成器 | [README](GFramework.Godot.SourceGenerators/README.md) |
## 内部支撑模块
以下目录目前不是独立采用入口,而是跟随所属模块维护的内部支撑组件:
| 目录 | 定位 | 跟随入口 |
| --- | --- | --- |
| `GFramework.Core.SourceGenerators.Abstractions` | `Core.SourceGenerators` 的内部契约层 | [GFramework.Core.SourceGenerators/README.md](GFramework.Core.SourceGenerators/README.md) |
| `GFramework.Godot.SourceGenerators.Abstractions` | `Godot.SourceGenerators` 的内部契约层 | [GFramework.Godot.SourceGenerators/README.md](GFramework.Godot.SourceGenerators/README.md) |
| `GFramework.SourceGenerators.Common` | 生成器家族共享的公共支撑代码 | [docs/zh-CN/source-generators/index.md](docs/zh-CN/source-generators/index.md) |
## 文档导航
仓库根 README 与文档站点保持同一套栏目命名:
@ -119,10 +130,13 @@ GFramework.sln
├─ GFramework.Game.Abstractions/
├─ GFramework.Godot/
├─ GFramework.Ecs.Arch/
├─ GFramework.Ecs.Arch.Abstractions/
├─ GFramework.Core.SourceGenerators/
├─ GFramework.Core.SourceGenerators.Abstractions/
├─ GFramework.Game.SourceGenerators/
├─ GFramework.Cqrs.SourceGenerators/
├─ GFramework.Godot.SourceGenerators/
├─ GFramework.Godot.SourceGenerators.Abstractions/
├─ GFramework.SourceGenerators.Common/
└─ docs/
```

View File

@ -25,6 +25,11 @@ help the current worktree land on the right recovery documents without scanning
- Purpose: continue the AI-First config runtime, generator, and consumer DX work for `GFramework.Game`.
- Tracking: `ai-plan/public/ai-first-config-system/todos/ai-first-config-system-tracking.md`
- Trace: `ai-plan/public/ai-first-config-system/traces/ai-first-config-system-trace.md`
- `documentation-full-coverage-governance`
- Purpose: govern full-coverage documentation inventory, module-wave remediation, and the README / docs / XML /
API-reference alignment baseline.
- Tracking: `ai-plan/public/documentation-full-coverage-governance/todos/documentation-full-coverage-governance-tracking.md`
- Trace: `ai-plan/public/documentation-full-coverage-governance/traces/documentation-full-coverage-governance-trace.md`
- `coroutine-optimization`
- Purpose: continue the coroutine semantics, host integration, observability, regression coverage, and migration-doc
follow-up work.
@ -38,10 +43,6 @@ help the current worktree land on the right recovery documents without scanning
- Purpose: continue the data repository persistence hardening plus the settings / serialization follow-up backlog.
- Tracking: `ai-plan/public/data-repository-persistence/todos/data-repository-persistence-tracking.md`
- Trace: `ai-plan/public/data-repository-persistence/traces/data-repository-persistence-trace.md`
- `documentation-governance-and-refresh`
- Purpose: continue the documentation governance, README hardening, and `docs/zh-CN` accuracy refresh work.
- Tracking: `ai-plan/public/documentation-governance-and-refresh/todos/documentation-governance-and-refresh-tracking.md`
- Trace: `ai-plan/public/documentation-governance-and-refresh/traces/documentation-governance-and-refresh-trace.md`
## Worktree To Active Topic Map
@ -64,10 +65,12 @@ help the current worktree land on the right recovery documents without scanning
- Priority 1: `data-repository-persistence`
- Branch: `docs/sdk-update-documentation`
- Worktree hint: `GFramework-update-documentation`
- Priority 1: `documentation-governance-and-refresh`
- Priority 1: `documentation-full-coverage-governance`
## Archived Topics
- `cqrs-cache-docs-hardening`
- Archive root: `ai-plan/public/archive/cqrs-cache-docs-hardening/`
- Note: archived topics stay outside the default `boot` context until a user explicitly requests historical review.
- `documentation-governance-and-refresh`
- Archive root: `ai-plan/public/archive/documentation-governance-and-refresh/`
- Note: PR #268 已合并;文档治理与 Godot 栏目刷新阶段已完成,后续仅作为历史恢复材料保留。

View File

@ -0,0 +1,62 @@
# Documentation Governance And Refresh 跟踪
## 目标
继续以“文档必须可追溯到源码、测试与真实接入方式”为原则,维护 `GFramework` 的仓库入口、模块入口与
`docs/zh-CN` 采用链路,避免 README、专题页与教程再次偏离当前实现。
## 当前恢复点
- 恢复点编号:`DOCUMENTATION-GOVERNANCE-REFRESH-RP-019`
- 当前阶段:`Completed`
- 当前焦点:
- 用户已确认 PR #268 合并,本 topic 对应的文档治理收口工作完成
- 当前目录将在本轮迁入 `ai-plan/public/archive/documentation-governance-and-refresh/`
- 后续若需历史回溯,应从 archive 中恢复,而不是继续把该 topic 作为 active 默认入口
## 当前状态摘要
- `docs/zh-CN/godot/` 当前高优先级页面集与 `docs/zh-CN/tutorials/godot-integration.md` 已完成源码优先收口
- PR #268 已合并,上一轮保留 active 的唯一原因已经解除
- 本 topic 已达到归档条件实现完成、校验完成、PR 生命周期结束
## 当前活跃事实
- 当前 worktree 下未发现 `ai-plan/private/` 恢复目录,本主题一直以 public artifacts 作为唯一恢复入口
- 已存在的阶段归档:
- `ai-plan/public/documentation-governance-and-refresh/archive/todos/documentation-governance-and-refresh-history-through-2026-04-22.md`
- `ai-plan/public/documentation-governance-and-refresh/archive/traces/documentation-governance-and-refresh-history-through-2026-04-22.md`
- 2026-04-22 之前的长篇历史已存在于 2026-04-18 与 RP-001 through RP-008 的归档文件中
- 当前待处理事项已清零;后续只保留历史查询价值
## 当前风险
- 后续历史定位风险:如果不把 topic 从 active 列表中移除,`boot` 会继续把已经完成的文档治理主题当作默认入口
- 缓解措施:本轮同步更新 `ai-plan/public/README.md` 并把整个 topic 目录迁入 `ai-plan/public/archive/`
- 文档回漂风险:未来若有新的 README / `docs/zh-CN` 变更,仍可能重新引入与源码不一致的表述
- 缓解措施:新任务应创建或复用新的 active topic而不是重启当前已完成主题
## 活跃文档
- 当前 trace[documentation-governance-and-refresh-trace.md](../traces/documentation-governance-and-refresh-trace.md)
- 2026-04-22 跟踪归档:[documentation-governance-and-refresh-history-through-2026-04-22.md](../archive/todos/documentation-governance-and-refresh-history-through-2026-04-22.md)
- 2026-04-22 trace 归档:[documentation-governance-and-refresh-history-through-2026-04-22.md](../archive/traces/documentation-governance-and-refresh-history-through-2026-04-22.md)
- 2026-04-18 历史归档:[documentation-governance-and-refresh-history-through-2026-04-18.md](../archive/todos/documentation-governance-and-refresh-history-through-2026-04-18.md)
- RP-001 到 RP-008 trace 归档:[documentation-governance-and-refresh-rp-001-through-rp-008.md](../archive/traces/documentation-governance-and-refresh-rp-001-through-rp-008.md)
## 验证说明
- `bash .agents/skills/gframework-doc-refresh/scripts/validate-all.sh docs/zh-CN/godot/index.md`
- `bash .agents/skills/gframework-doc-refresh/scripts/validate-all.sh docs/zh-CN/godot/architecture.md`
- `bash .agents/skills/gframework-doc-refresh/scripts/validate-all.sh docs/zh-CN/godot/scene.md`
- `bash .agents/skills/gframework-doc-refresh/scripts/validate-all.sh docs/zh-CN/godot/ui.md`
- `bash .agents/skills/gframework-doc-refresh/scripts/validate-all.sh docs/zh-CN/godot/signal.md`
- `bash .agents/skills/gframework-doc-refresh/scripts/validate-all.sh docs/zh-CN/godot/extensions.md`
- `bash .agents/skills/gframework-doc-refresh/scripts/validate-all.sh docs/zh-CN/godot/logging.md`
- `bash .agents/skills/gframework-doc-refresh/scripts/validate-all.sh docs/zh-CN/tutorials/godot-integration.md`
- `cd docs && bun run build`
## 下一步
1. 将整个 `documentation-governance-and-refresh` 目录迁入 `ai-plan/public/archive/`
2. 从 `ai-plan/public/README.md` 删除该 topic 的 active 声明与 worktree 映射

View File

@ -0,0 +1,26 @@
# Documentation Governance And Refresh Trace
## 2026-04-22
### 当前恢复点RP-019
- 本轮按 `boot` 恢复 `documentation-governance-and-refresh` 主题
- 用户明确说明 PR #268 已合并,因此该主题不再需要保持 active 以等待 review follow-up
- 当前主题满足完成条件:文档页已完成校验、`docs` 站点先前已构建通过、PR 生命周期结束
- 本轮将把整个主题目录迁入 `ai-plan/public/archive/documentation-governance-and-refresh/`
- `ai-plan/public/README.md` 也将在本轮删除该 topic 的 active 声明与 worktree 映射
### 当前决策
- 当前主题正式归档,不再作为 `boot` 默认入口
- 若未来出现新的文档治理任务,应创建新的 active topic 或挂到新的现役主题,而不是恢复本目录
- 现有 tracking / trace 留在 archive 中作为历史恢复材料
### 验证
- `cd docs && bun run build`
- 结果:通过;无构建失败,主题满足归档前的最终验证要求
### 下一步
1. 若需回看本阶段历史,从 `ai-plan/public/archive/documentation-governance-and-refresh/` 读取归档材料

View File

@ -0,0 +1,77 @@
# Documentation Full Coverage Governance Validation History Through RP-007
以下内容从 active tracking 中迁出,用于保留 `DOCUMENTATION-FULL-COVERAGE-GOV-RP-001`
`DOCUMENTATION-FULL-COVERAGE-GOV-RP-007` 的详细验证历史。默认 `boot` 只需要读取 active tracking 中的最新摘要;
若需要追溯早期验证命令与结果,再回到本归档文件。
## 详细验证历史
- `bash .agents/skills/gframework-doc-refresh/scripts/validate-all.sh docs/zh-CN/abstractions/index.md`
- 结果:通过
- `bash .agents/skills/gframework-doc-refresh/scripts/validate-all.sh docs/zh-CN/abstractions/ecs-arch-abstractions.md`
- 结果:通过
- `bash .agents/skills/gframework-doc-refresh/scripts/validate-all.sh docs/zh-CN/api-reference/index.md`
- 结果:通过
- `bash .agents/skills/gframework-doc-refresh/scripts/validate-all.sh docs/zh-CN/core/index.md`
- 结果:通过
- 备注:`2026-04-22` 在补充 Core XML inventory 后重新验证
- `bash .agents/skills/gframework-doc-refresh/scripts/validate-all.sh docs/zh-CN/abstractions/core-abstractions.md`
- 结果:通过
- 备注:`2026-04-22` 在补充 Core.Abstractions XML inventory 后重新验证
- `cd docs && bun run build`
- 结果:通过
- 备注:`2026-04-22` 重新构建通过;仅保留 VitePress 大 chunk warning无构建失败
- `dotnet build GFramework.Ecs.Arch.Abstractions/GFramework.Ecs.Arch.Abstractions.csproj -c Release -p:RestoreFallbackFolders=`
- 结果:通过
- 备注:`0 Warning(s) / 0 Error(s)`
- `DOTNET_CLI_HOME=/tmp/dotnet-home dotnet build GFramework.Core.Abstractions/GFramework.Core.Abstractions.csproj -c Release -p:RestoreFallbackFolders=`
- 结果:通过
- 备注:`0 Warning(s) / 0 Error(s)`
- `bash .agents/skills/gframework-doc-refresh/scripts/validate-all.sh docs/zh-CN/ecs/index.md`
- 结果:通过
- 备注:`2026-04-22` 在重写 ECS landing 后重新验证
- `bash .agents/skills/gframework-doc-refresh/scripts/validate-all.sh docs/zh-CN/ecs/arch.md`
- 结果:通过
- 备注:`2026-04-22` 在重写 Arch ECS 专题页后重新验证
- `bash .agents/skills/gframework-doc-refresh/scripts/validate-all.sh docs/zh-CN/abstractions/ecs-arch-abstractions.md`
- 结果:通过
- 备注:`2026-04-22` 在补充抽象页 XML inventory 后重新验证
- `cd docs && bun run build`
- 结果:通过
- 备注:`2026-04-22` 在 Ecs 波次重写后重新构建通过;仅保留 VitePress 大 chunk warning无构建失败
- `bash .agents/skills/gframework-doc-refresh/scripts/validate-all.sh docs/zh-CN/core/cqrs.md`
- 结果:通过
- 备注:`2026-04-22` 在重写 `Cqrs` family landing 后重新验证
- `bash .agents/skills/gframework-doc-refresh/scripts/validate-all.sh docs/zh-CN/source-generators/cqrs-handler-registry-generator.md`
- 结果:通过
- 备注:`2026-04-22` 在新增 `Cqrs.SourceGenerators` 专题页后验证通过
- `python3` 轻量 XML inventory 扫描
- 结果:通过
- 备注:`2026-04-22` 确认 `GFramework.Cqrs``Internal/``14/14``GFramework.Cqrs.SourceGenerators/Cqrs/``3/3``GFramework.Cqrs.Abstractions/Cqrs/``20/20`
- `DOTNET_CLI_HOME=/tmp/dotnet-home dotnet build GFramework.Cqrs.SourceGenerators/GFramework.Cqrs.SourceGenerators.csproj -c Release -p:RestoreFallbackFolders=`
- 结果:通过
- 备注:保留既有 `NU1900``MA0051` warnings无新增编译错误
- `DOTNET_CLI_HOME=/tmp/dotnet-home dotnet build GFramework.Cqrs/GFramework.Cqrs.csproj -c Release`
- 结果:失败
- 备注:当前环境会命中失效的 Windows fallback package folder并在多目标 inner build 阶段触发 `MSB4276` / `MSB4018`;失败原因已记录为环境阻塞,不属于本轮文档改动回归
- `cd docs && bun run build`
- 结果:通过
- 备注:`2026-04-22``Cqrs` 波次文档刷新后重新构建通过;仅保留 VitePress 大 chunk warning无构建失败
- `bash .agents/skills/gframework-doc-refresh/scripts/validate-all.sh docs/zh-CN/abstractions/game-abstractions.md`
- 结果:通过
- 备注:`2026-04-23` 在重写 `Game.Abstractions` 页面后验证通过
- `bash .agents/skills/gframework-doc-refresh/scripts/validate-all.sh docs/zh-CN/game/index.md`
- 结果:通过
- 备注:`2026-04-23` 在补充 frontmatter 与 XML inventory 后重新验证
- `python3` 轻量 XML inventory 扫描
- 结果:通过
- 备注:`2026-04-23` 确认 `GFramework.Game``56/56``GFramework.Game.Abstractions``80/80``GFramework.Game.SourceGenerators``2/2`
- `cd docs && bun run build`
- 结果:通过
- 备注:`2026-04-23``Game` 波次文档刷新后重新构建通过;仅保留 VitePress 大 chunk warning无构建失败
- `cd docs && bun run build`
- 结果:通过
- 备注:`2026-04-23` 在更新 `AGENTS.md` 的 WSL Git 优先级后重新构建通过;仅保留 VitePress 大 chunk warning无构建失败
- `cd docs && bun run build`
- 结果:通过
- 备注:`2026-04-23` 在推进 `DOCUMENTATION-FULL-COVERAGE-GOV-RP-007`、回写 `Game` family 巡检结论后重新构建通过;仅保留 VitePress 大 chunk warning无构建失败

View File

@ -0,0 +1,124 @@
# Documentation Full Coverage Governance 跟踪
## 目标
建立一个长期 active topic持续治理 `GFramework` 的 README、`docs/zh-CN`、站点导航、XML 文档和 API
参考链路,避免历史上的阶段性刷新完成后再次回漂。
- 用源码、测试、`*.csproj` 和必要的 `ai-libs/` 证据校正文档
- 以模块族为单位闭环 README、landing page、专题页、教程入口和 API 参考链路
- 明确哪些目录是可直接消费模块,哪些只是内部支撑模块
- 把 XML 文档缺口纳入治理范围,而不是只刷新 Markdown
## 当前恢复点
- 恢复点编号:`DOCUMENTATION-FULL-COVERAGE-GOV-RP-008`
- 当前阶段:`Phase 5 - Governance Maintenance`
- 当前焦点:
- 消化 PR #271 的 latest-head review follow-up修正仍在本地成立的 docs / skill / ai-plan 问题
- 将 active tracking 的重复验证明细迁出默认 boot 路径,只保留最新可恢复摘要
- 评估是否需要把 `Godot` family 的关键 XML inventory 摘要迁回 active topic
## 当前状态摘要
- 已归档的 `documentation-governance-and-refresh` 仅保留为历史证据,不再作为默认 `boot` 入口
- 本轮已消化的 PR #271 review follow-up
- 为 `.agents/skills/gframework-pr-review/scripts/fetch_current_pr_review.py` 补齐 WSL worktree 下的显式 Linux Git 绑定,避免 `git.exe` 在当前会话触发 `Exec format error`
- 同步更新 `.agents/skills/gframework-pr-review/SKILL.md`,改为与 `AGENTS.md` 一致的 Git 策略,并把命令示例统一到 `.agents/...` 路径
- 为 `docs/zh-CN/source-generators/cqrs-handler-registry-generator.md` 补充 marker 类型放置与命名约定说明
- 从 `docs/zh-CN/abstractions/ecs-arch-abstractions.md` 删除误放的 source-generator 内部模块提醒,并微调 `docs/zh-CN/ecs/index.md` 的边界说明语序
- 为 `ai-plan/public/archive/documentation-governance-and-refresh/traces/documentation-governance-and-refresh-trace.md` 的归档验证补写结果态
- 将 RP-001 至 RP-007 的详细验证历史迁入 `ai-plan/public/documentation-full-coverage-governance/archive/todos/documentation-full-coverage-governance-validation-history-through-rp-007.md`
- 本轮已确认的消费属性结论:
- `GFramework.Ecs.Arch.Abstractions`:可打包直接消费模块,需要 README 和文档入口
- `GFramework.Core.SourceGenerators.Abstractions``IsPackable=false`,按内部支撑模块处理
- `GFramework.Godot.SourceGenerators.Abstractions``IsPackable=false`,按内部支撑模块处理
- `GFramework.SourceGenerators.Common``IsPackable=false`,按内部支撑模块处理
- 本轮已完成的治理动作:
- 新建 `GFramework.Ecs.Arch.Abstractions/README.md`
- 在根 `README.md` 中补齐 `GFramework.Ecs.Arch.Abstractions` 入口,并声明内部支撑模块 owner
- 为抽象接口栏目补齐 `Ecs.Arch.Abstractions` 页面与 sidebar 入口
- 将 `docs/zh-CN/api-reference/index.md` 重写为模块到 XML / README / 教程的阅读链路入口
- 为 `GFramework.Core/README.md` 补齐 `Services``Configuration``Environment``Pool``Rule``Time` 等当前目录映射
- 为 `GFramework.Core.Abstractions/README.md` 补齐契约族地图与 XML 阅读重点
- 将 `docs/zh-CN/abstractions/core-abstractions.md` 从过时的接口摘录页重写为契约边界 / 包关系 / 最小接入路径页面
- 为 `docs/zh-CN/core/index.md` 补齐 frontmatter、能力域导航和 API / XML 阅读入口
- 为 `GFramework.Core/README.md``GFramework.Core.Abstractions/README.md` 补齐类型族级 XML 覆盖基线入口
- 为 `docs/zh-CN/core/index.md``docs/zh-CN/abstractions/core-abstractions.md` 增加“类型族 -> XML 覆盖状态 -> 代表类型”的 inventory
- 基于顶层目录轻量盘点确认:`Core` / `Core.Abstractions` 当前公开 / 内部类型声明都已带 XML 注释,成员级审计留待后续波次
- 重写 `docs/zh-CN/ecs/index.md`,收敛当前 ECS family 的包边界、采用顺序和 XML inventory
- 重写 `docs/zh-CN/ecs/arch.md`,明确 `UseArch(...)` 需早于 `Initialize()` 的真实接入时机
- 刷新 `GFramework.Ecs.Arch/README.md`,使运行时 README 与源码 / 测试一致
- 为 `GFramework.Ecs.Arch.Abstractions/README.md``docs/zh-CN/abstractions/ecs-arch-abstractions.md` 补齐类型族级 XML inventory
- 重写 `docs/zh-CN/core/cqrs.md`,将其收敛为 `Cqrs` family landing并补齐运行时 / 契约层 / 生成器的 XML inventory
- 新建 `docs/zh-CN/source-generators/cqrs-handler-registry-generator.md`,为 `Cqrs.SourceGenerators` 补齐站内专题入口
- 更新 `docs/zh-CN/source-generators/index.md``docs/zh-CN/api-reference/index.md` 与 VitePress sidebar使 `Cqrs` family 的 generator 入口可导航
- 为 `GFramework.Cqrs/Internal/CqrsHandlerRegistrar.cs``GFramework.Cqrs.SourceGenerators/Cqrs/CqrsHandlerRegistryGenerator.cs` 中缺失的内部类型补齐 XML 注释,使本轮轻量 inventory 达到声明级闭环
- 为 `GFramework.Game/README.md``GFramework.Game.Abstractions/README.md``GFramework.Game.SourceGenerators/README.md` 补齐 `Game` family 的类型族级 XML inventory
- 为 `docs/zh-CN/game/index.md` 补齐 frontmatter并增加 `Game` / `Game.Abstractions` / `Game.SourceGenerators` 的 XML 覆盖基线入口
- 将 `docs/zh-CN/abstractions/game-abstractions.md` 从失真的旧接口摘录页重写为契约边界 / 包关系 / 最小接入路径页面
- 基于顶层目录轻量盘点确认:`GFramework.Game``56/56``GFramework.Game.Abstractions``80/80``GFramework.Game.SourceGenerators``2/2`,当前公开 / 内部类型声明都已带 XML 注释
- 更新 `AGENTS.md` 的 WSL Git 策略,将显式 `--git-dir` / `--work-tree` 绑定提升为高于 `git.exe` 的默认优先级
- 记录当前环境偏差:本会话 `git.exe` 可解析但执行会触发 `Exec format error`,而 plain Linux `git` 会命中 worktree 路径翻译错误,需要显式仓库绑定
- 完成 `Game` family 巡检,确认 `docs/zh-CN/game/config-system.md``scene.md``ui.md``docs/zh-CN/source-generators/index.md` 的核心采用说明、包关系与交叉引用仍与当前源码 / README 一致,没有发现需要立刻修正的回漂
## Inventory第一版
| 模块族 | 当前状态 | 当前证据 | 下一动作 |
| --- | --- | --- | --- |
| `Core` / `Core.Abstractions` | `README / landing / 类型族级 XML inventory 已收口,成员级审计待补齐` | 根 README、模块 README、`docs/zh-CN/core/**``docs/zh-CN/abstractions/core-abstractions.md` 已对齐当前目录与类型族基线 | 进入巡检;如有新 API 变更,再追加成员级 XML 审计 |
| `Cqrs` / `Cqrs.Abstractions` / `Cqrs.SourceGenerators` | `README / landing / generator topic / 类型族级 XML inventory 已收口,成员级审计待补齐` | `GFramework.Cqrs/README.md``GFramework.Cqrs.Abstractions/README.md``GFramework.Cqrs.SourceGenerators/README.md``docs/zh-CN/core/cqrs.md``docs/zh-CN/source-generators/cqrs-handler-registry-generator.md``docs/zh-CN/api-reference/index.md` 已对齐当前源码与测试 | 转入巡检;下一波切到 `Game` family 的 XML / 教程链路审计 |
| `Game` / `Game.Abstractions` / `Game.SourceGenerators` | `README / landing / abstractions / 类型族级 XML inventory 已收口,成员级审计待补齐` | `GFramework.Game/README.md``GFramework.Game.Abstractions/README.md``GFramework.Game.SourceGenerators/README.md``docs/zh-CN/game/index.md``docs/zh-CN/abstractions/game-abstractions.md` 已对齐当前源码与目录基线 | 转入巡检;优先抽查 `config-system``scene``ui``source-generators` 交叉链路是否回漂 |
| `Godot` / `Godot.SourceGenerators` | `已验证` | 上一轮归档 topic 已完成核心 landing / topic / tutorial 校验 | 进入巡检周期,重点看回漂 |
| `Ecs.Arch` / `Ecs.Arch.Abstractions` | `README / landing / abstractions / 类型族级 XML inventory 已收口,成员级审计待补齐` | `GFramework.Ecs.Arch/README.md``GFramework.Ecs.Arch.Abstractions/README.md``docs/zh-CN/ecs/**``docs/zh-CN/abstractions/ecs-arch-abstractions.md` 已对齐当前源码与测试 | 转入巡检;后续仅在运行时公共 API 变动时补成员级 XML 细审 |
| `SourceGenerators.Common``*.SourceGenerators.Abstractions` | `已判定为内部支撑` | `*.csproj` 明确 `IsPackable=false` | 由所属模块 README 与生成器栏目说明 owner不建独立采用页 |
## 缺口分级
- `P0`
- 错误采用路径、错误包关系、错误 API / 生命周期语义
- 站点导航死链、空 landing page、明显错误的模块 owner
- `P1`
- 直接消费模块缺 README 或缺对应 docs 入口
- README / docs 示例与源码实现不一致
- 教程仍引用已经过时的默认接线方式
- `P2`
- 结构重复、交叉链接不足、API 参考链路过薄
- 站内页面存在事实正确但组织方式不利于定位的内容
## 当前风险
- 当前 `Core` / `Core.Abstractions` 只完成了类型族级 XML 基线,不等于成员级契约全审计
- 缓解措施:后续只在共享抽象或高风险生命周期接口发生改动时补成员级细审,不在本轮扩张范围
- `Godot` family 的治理结论主要留在已归档 topic 中active topic 当前只保留摘要
- 缓解措施:下一恢复点优先判断是否要把关键 XML inventory 摘要迁回 active topic避免后续 boot 仍过度依赖 archive
- 新功能分支若修改 README / docs / 公共 API 却不挂文档 topic仍可能回漂
- 缓解措施:将本 topic 作为长期 active topic 保留,并在后续巡检中记录回漂来源
- VitePress 页面不能直接链接到 `docs/` 目录之外的模块 `README.md`
- 缓解措施:站内页面用模块路径文本或站内 API 入口表达,仓库级 README 仍保留仓库文件链接
- `GFramework.Cqrs` 在当前 WSL / dotnet 环境下,本地 build 仍会读取失效的 fallback package folder 配置,导致无法完成该项目的标准编译验证
- 缓解措施:本轮先以 `GFramework.Cqrs.SourceGenerators` 编译通过和 docs site build 通过作为有效验证,并在后续环境治理或构建脚本清理时单独处理 `RestoreFallbackFolders` / 资产文件问题
- 当前 WSL 会话中 `git.exe` 虽然可解析,但不能执行
- 缓解措施:把显式 `--git-dir` / `--work-tree` 绑定上升为仓库默认回退策略,并仅把 `git.exe` 保留为可执行时的次级 fallback
## 验证说明
- 详细验证历史已归档到 `ai-plan/public/documentation-full-coverage-governance/archive/todos/documentation-full-coverage-governance-validation-history-through-rp-007.md`
- `2026-04-23` `python3 -B -c "from pathlib import Path; compile(Path('.agents/skills/gframework-pr-review/scripts/fetch_current_pr_review.py').read_text(encoding='utf-8'), '.agents/skills/gframework-pr-review/scripts/fetch_current_pr_review.py', 'exec')"`
- 结果:通过
- `2026-04-23` `python3 .agents/skills/gframework-pr-review/scripts/fetch_current_pr_review.py --json-output /tmp/gframework-current-pr-review.json`
- 结果:通过;成功抓取 PR `#271`,并确认当前 latest-head review threads 为 `4` 条 open
- `2026-04-23` `bash .agents/skills/gframework-doc-refresh/scripts/validate-all.sh docs/zh-CN/source-generators/cqrs-handler-registry-generator.md`
- 结果:通过
- `2026-04-23` `bash .agents/skills/gframework-doc-refresh/scripts/validate-all.sh docs/zh-CN/ecs/index.md`
- 结果:通过
- `2026-04-23` `bash .agents/skills/gframework-doc-refresh/scripts/validate-all.sh docs/zh-CN/abstractions/ecs-arch-abstractions.md`
- 结果:通过
- `2026-04-23` `cd docs && bun run build`
- 结果:通过;仅保留既有 VitePress 大 chunk warning无构建失败
## 下一步
1. 完成本轮 PR #271 follow-up 的针对性验证与 docs build确认 open threads 是否都已被本地收敛
2. 推送当前分支后重新执行 `$gframework-pr-review`,确认 PR #271 的 latest-head open threads 是否按预期收敛
3. 评估是否需要把 `Godot` family 的关键 XML inventory 摘要迁回 active topic避免长期治理只依赖 archive 恢复

View File

@ -0,0 +1,275 @@
# Documentation Full Coverage Governance Trace
## 2026-04-22
### 当前恢复点RP-001
- 按长期治理计划新建 active topic `documentation-full-coverage-governance`
- 在 `ai-plan/public/README.md` 中将当前分支 `docs/sdk-update-documentation` 映射到该 topic
- 复核已知缺口模块的 `*.csproj` 后确认:
- `GFramework.Ecs.Arch.Abstractions` 是可打包消费模块,需要独立 README
- `GFramework.Core.SourceGenerators.Abstractions``GFramework.Godot.SourceGenerators.Abstractions`
`GFramework.SourceGenerators.Common` 都是 `IsPackable=false` 的内部支撑模块
- 基于该结论,本轮没有为内部支撑模块新增独立 README而是在根 README 与 abstractions / API 入口中明确其 owner
### 当前决策
- 新主题的完成条件采用长期治理口径:`P0` 清零、无 README 缺失、无导航死链,并完成连续两轮稳定巡检
- 本轮先做治理基础设施与 inventory不把整个长期计划伪装成单轮完成
- `api-reference` 页面改为“模块 -> README / docs / XML / tutorial”的阅读链路入口避免继续维护失真的伪签名列表
- `Ecs.Arch` family 被列为高优先 backlog抽象层入口已补齐但 runtime docs 仍需按源码重写
- `Core` / `Core.Abstractions` 波次先收口 README、landing page 和 abstractions 页的目录映射,再补显式 XML 覆盖 inventory
- VitePress 站内页面不直接链接仓库根模块 `README.md`;站内仅保留可构建的 docs 链接,模块 README 以文本路径或仓库 README 承接
### 当前恢复点RP-002
- 完成 `Core` / `Core.Abstractions` 的类型族级 XML inventory
- `GFramework.Core/README.md`
- `GFramework.Core.Abstractions/README.md`
- `docs/zh-CN/core/index.md`
- `docs/zh-CN/abstractions/core-abstractions.md`
- 通过顶层目录轻量盘点确认:
- `GFramework.Core` 当前各目录族的公开 / 内部类型声明都已带 XML 注释
- `GFramework.Core.Abstractions` 当前各契约目录族的公开 / 内部类型声明都已带 XML 注释
- 这轮 inventory 明确限定为“类型声明级基线”,不把结果表述成成员级 XML 合规审计
### 当前决策RP-002
- XML inventory 同时落在模块 README 和站内 landing page
- README 提供仓库侧入口,方便从包目录直接恢复上下文
- docs landing 提供更细的类型族 / 代表类型 / 阅读重点表格,方便站内导航
- `Core` 波次在补齐基线后转入巡检,不继续在本轮展开成员级 ``<param>`` / ``<returns>`` 审计
- 下一恢复点切换到 `Ecs` 波次,优先处理仍明显失真的 runtime docs
### 当前验证
- 文档校验:
- `validate-all.sh docs/zh-CN/abstractions/index.md`:通过
- `validate-all.sh docs/zh-CN/abstractions/ecs-arch-abstractions.md`:通过
- `validate-all.sh docs/zh-CN/api-reference/index.md`:通过
- `validate-all.sh docs/zh-CN/core/index.md`:通过
- `validate-all.sh docs/zh-CN/abstractions/core-abstractions.md`:通过
- 构建校验:
- `cd docs && bun run build`:通过
- `DOTNET_CLI_HOME=/tmp/dotnet-home dotnet build GFramework.Core.Abstractions/GFramework.Core.Abstractions.csproj -c Release -p:RestoreFallbackFolders=`:通过,`0 Warning(s) / 0 Error(s)`
- `dotnet build GFramework.Ecs.Arch.Abstractions/GFramework.Ecs.Arch.Abstractions.csproj -c Release -p:RestoreFallbackFolders=`:通过,`0 Warning(s) / 0 Error(s)`
### 当前验证RP-002
- 文档校验:
- `validate-all.sh docs/zh-CN/core/index.md`:通过
- `validate-all.sh docs/zh-CN/abstractions/core-abstractions.md`:通过
- 构建校验:
- `cd docs && bun run build`:通过;仅保留 VitePress 大 chunk warning无构建失败
### 当前恢复点RP-003
- 完成 `Ecs.Arch` 波次的运行时文档刷新:
- `docs/zh-CN/ecs/index.md`
- `docs/zh-CN/ecs/arch.md`
- `GFramework.Ecs.Arch/README.md`
- 为 `Ecs.Arch.Abstractions` 补齐与运行时页同粒度的 XML inventory
- `GFramework.Ecs.Arch.Abstractions/README.md`
- `docs/zh-CN/abstractions/ecs-arch-abstractions.md`
- 明确记录一个关键采用事实:
- `UseArch(...)` 必须早于 `Initialize()` 调用
- 该结论以 `ArchExtensions` 的模块注册方式和 `ExplicitRegistrationTests` 为证据
- 将 `Ecs.Arch` family 从“入口存在但失真”推进到“README / landing / abstractions / XML inventory 已对齐源码与测试”
### 当前决策RP-003
- `Ecs` 波次继续采用与 `Core` 相同的治理粒度:
- 模块 README 承担仓库入口
- `docs/zh-CN/ecs/index.md` 承担模块族 landing
- `docs/zh-CN/ecs/arch.md` 承担运行时默认实现专题页
- `docs/zh-CN/abstractions/ecs-arch-abstractions.md` 承担契约边界专题页
- `EnableStatistics` 当前仅保留在公开配置面上;文档不再把它写成已验证的运行时行为
- 下一恢复点切换到 `Cqrs` 波次,优先解决入口分散和 API / XML 阅读链路不统一的问题
### 当前验证RP-003
- 文档校验:
- `validate-all.sh docs/zh-CN/ecs/index.md`:通过
- `validate-all.sh docs/zh-CN/ecs/arch.md`:通过
- `validate-all.sh docs/zh-CN/abstractions/ecs-arch-abstractions.md`:通过
- 构建校验:
- `cd docs && bun run build`:通过;仅保留 VitePress 大 chunk warning无构建失败
### 下一步
1. 在 `Cqrs` 波次核对模块 README、`docs/zh-CN/core/cqrs.md``docs/zh-CN/source-generators/**` 的真实 owner
2. 决定 `Cqrs` family 是补 dedicated landing 还是拆分现有入口页
### 当前恢复点RP-004
- 完成 `Cqrs` 波次的模块族入口刷新:
- 重写 `docs/zh-CN/core/cqrs.md`
- 新建 `docs/zh-CN/source-generators/cqrs-handler-registry-generator.md`
- 更新 `docs/zh-CN/source-generators/index.md`
- 更新 `docs/zh-CN/api-reference/index.md`
- 更新 `docs/.vitepress/config.mts`
- 将 `Cqrs` family 从“README 已存在但 generator 入口分散”推进到“runtime / abstractions / source generator 都有明确站内入口”
- 为 `GFramework.Cqrs/Internal/CqrsHandlerRegistrar.cs`
`GFramework.Cqrs.SourceGenerators/Cqrs/CqrsHandlerRegistryGenerator.cs` 中缺失的内部类型补齐 XML 注释
- 基于轻量扫描确认:
- `GFramework.Cqrs.Abstractions/Cqrs/` 当前类型声明级 XML 覆盖为 `20/20`
- `GFramework.Cqrs` 根入口与 `Internal/` 已补到 `19/19`
- `GFramework.Cqrs.SourceGenerators/Cqrs/` 当前类型声明级 XML 覆盖为 `3/3`
### 当前决策RP-004
- `docs/zh-CN/core/cqrs.md` 继续保留在 `Core` 栏目,但其角色调整为 `Cqrs` family landing而不再只是 runtime 简介页
- `Cqrs.SourceGenerators` 不单独新建一级导航栏目,而是在 `source-generators` 栏目内补一个专用专题页,保持站点 taxonomy 稳定
- generator 入口以“专题页 + API reference 链接 + sidebar”三点联动而不是只在 `source-generators/index.md` 留一个段落链接
- XML inventory 仍维持“类型声明级基线”口径,不在本轮扩展成成员级 `param/returns/exception` 细审
### 当前验证RP-004
- 文档校验:
- `validate-all.sh docs/zh-CN/core/cqrs.md`:通过
- `validate-all.sh docs/zh-CN/source-generators/cqrs-handler-registry-generator.md`:通过
- 轻量 XML inventory
- `GFramework.Cqrs/Internal/``14/14`
- `GFramework.Cqrs.Abstractions/Cqrs/``20/20`
- `GFramework.Cqrs.SourceGenerators/Cqrs/``3/3`
- 构建校验:
- `dotnet build GFramework.Cqrs.SourceGenerators/GFramework.Cqrs.SourceGenerators.csproj -c Release -p:RestoreFallbackFolders=`:通过
- `cd docs && bun run build`:通过;仅保留 VitePress 大 chunk warning无构建失败
- `dotnet build GFramework.Cqrs/GFramework.Cqrs.csproj -c Release`:失败;当前 WSL / dotnet 环境仍引用失效的 Windows fallback package folder并在多目标 inner build 阶段触发 `MSB4276` / `MSB4018`
### 下一步
1. 切换到 `Game` family 波次,按 `Core` / `Ecs` / `Cqrs` 已验证模板继续补 XML inventory 与教程链路
2. 把 `GFramework.Cqrs` 的本地构建阻塞留给后续环境治理或构建脚本清理,不在本 topic 内扩张为环境修复任务
### 当前恢复点RP-005
- 完成 `Game` 波次的模块族入口刷新:
- 更新 `GFramework.Game/README.md`
- 更新 `GFramework.Game.Abstractions/README.md`
- 更新 `GFramework.Game.SourceGenerators/README.md`
- 更新 `docs/zh-CN/game/index.md`
- 重写 `docs/zh-CN/abstractions/game-abstractions.md`
- 将 `Game` family 从“README / 页面存在但缺少可审计 XML 入口,且 abstractions 页失真”推进到“runtime / abstractions / source generator 都有声明级 XML inventory 与真实采用边界”
- 基于轻量扫描确认:
- `GFramework.Game` 当前类型声明级 XML 覆盖为 `56/56`
- `GFramework.Game.Abstractions` 当前类型声明级 XML 覆盖为 `80/80`
- `GFramework.Game.SourceGenerators` 当前类型声明级 XML 覆盖为 `2/2`
### 当前决策RP-005
- `docs/zh-CN/abstractions/game-abstractions.md` 不再维护虚构接口摘录,而是与源码中的 `Config` / `Data` / `Setting` / `Scene` / `UI` / `Routing` 契约分组保持一致
- `Game.SourceGenerators` 继续以 `README + docs/zh-CN/game/config-system.md + docs/zh-CN/source-generators/index.md` 组成入口,不额外新增只为凑数量的专题页
- `docs/zh-CN/game/index.md` 补 frontmatter并承担 `Game` family 的 XML 基线入口;更细的类型族说明继续留在模块 README 与 abstractions 页
### 当前验证RP-005
- 文档校验:
- `validate-all.sh docs/zh-CN/abstractions/game-abstractions.md`:通过
- `validate-all.sh docs/zh-CN/game/index.md`:通过
- 轻量 XML inventory
- `GFramework.Game``56/56`
- `GFramework.Game.Abstractions``80/80`
- `GFramework.Game.SourceGenerators``2/2`
- 构建校验:
- `cd docs && bun run build`:通过;仅保留 VitePress 大 chunk warning无构建失败
### 下一步
1. 进入 `Game` family 巡检,优先检查 `config-system.md``scene.md``ui.md``source-generators/index.md` 的交叉引用是否回漂
2. 评估是否需要把 `Godot` family 的关键 XML inventory 摘要迁回 active topic减少对 archive 的依赖
### 当前恢复点RP-006
- 更新 `AGENTS.md` 的 WSL Git 规则:
- 将显式 `git --git-dir=<...> --work-tree=<...>` 绑定提升为高于 `git.exe` 的默认优先级
- 明确 plain Linux `git` 命中 worktree 路径翻译错误时,应先切到显式绑定而不是直接改用 `git.exe`
- 明确 `git.exe` 只有在当前会话可执行时才作为次级 fallback
- 记录本次恢复任务的环境偏差:
- `git.exe` 在当前 WSL 会话中可解析,但执行会触发 `Exec format error`
- plain `git` 会把 worktree 元数据路径翻译错并报“not a git repository”
- 显式 `--git-dir` / `--work-tree` 绑定是本次已验证可用的 Git 操作方式
### 当前决策RP-006
- 把 Git 回退顺序写进 `AGENTS.md`,而不是只留在一次性的聊天上下文里
- 不额外扩张 `gframework-boot` skill因为它本身不内嵌 Git 选择逻辑,继续由 `AGENTS.md` 作为唯一准则
- 继续把 `git.exe` 保留为 fallback而不是完全删除避免在可执行的 WSL 会话里丢掉可用路径
### 当前验证RP-006
- 构建校验:
- `cd docs && bun run build`:通过;仅保留 VitePress 大 chunk warning无构建失败
### 下一步
1. 继续 `Game` family 巡检,优先检查 `config-system.md``scene.md``ui.md``source-generators/index.md` 的交叉引用是否回漂
2. 评估是否需要把 `Godot` family 的关键 XML inventory 摘要迁回 active topic减少对 archive 的依赖
### 当前恢复点RP-007
- 完成 `Game` family 巡检:
- 复核 `docs/zh-CN/game/config-system.md`
- 复核 `docs/zh-CN/game/scene.md`
- 复核 `docs/zh-CN/game/ui.md`
- 复核 `docs/zh-CN/source-generators/index.md`
- 对照 `GFramework.Game``GFramework.Game.Abstractions``GFramework.Game.SourceGenerators` README 与相关源码 / 测试后,未发现需要立刻修正的采用语义回漂
- 重点确认的真实语义包括:
- `GameConfigBootstrap` / `RegisterAllGeneratedConfigTables(...)` / `GFrameworkConfigSchemaDirectory` 的配置入口仍与文档示例一致
- `SceneRouterBase` 仍通过 `SemaphoreSlim` 串行化切换,并拒绝重复 `sceneKey` 入栈
- `UiRouterBase` 仍将 `Page` 层与 `Overlay` / `Modal` / `Toast` / `Topmost` 分为两套入口,且 `Show(..., UiLayer.Page)` 会直接拒绝
### 当前决策RP-007
- 本轮不为“巡检通过”硬造文档改动,先把结论写回 active topic保持恢复点准确
- `Game` family 暂时转入稳定巡检,不在没有源码变化的情况下重复改写 landing page
- 默认下一步切到 `Godot` family 摘要是否回迁,减少长期治理对 archive topic 的依赖
### 当前验证RP-007
- 构建校验:
- `cd docs && bun run build`:通过;仅保留 VitePress 大 chunk warning无构建失败
### 下一步
1. 评估是否需要把 `Godot` family 的关键 XML inventory 摘要迁回 active topic
2. 若不需要迁回,则继续抽查 README / landing page / API reference 之间的 cross-link 是否出现新的漂移
### 当前恢复点RP-008
- 使用 `$gframework-pr-review` 抓取当前分支 PR `#271` 后,确认 latest head review threads 仍有 `4` 条 open
- `docs/zh-CN/source-generators/cqrs-handler-registry-generator.md` 的 marker 类型约定说明缺口
- `docs/zh-CN/ecs/index.md` 的边界说明语序问题
- `docs/zh-CN/abstractions/ecs-arch-abstractions.md` 误放的 source-generator 内部模块提醒
- `ai-plan/public/documentation-full-coverage-governance/todos/documentation-full-coverage-governance-tracking.md` 的验证历史过长,以及
`ai-plan/public/archive/documentation-governance-and-refresh/traces/documentation-governance-and-refresh-trace.md` 缺少显式结果态
- 在当前 WSL 会话里,`gframework-pr-review` 脚本先命中了 `git.exe``Exec format error`
- 已将 `.agents/skills/gframework-pr-review/scripts/fetch_current_pr_review.py` 改为优先使用 Linux `git` 的显式
`--git-dir` / `--work-tree` 绑定,并仅在无法建立该绑定时回退到旧的可执行解析逻辑
- 已同步更新 `.agents/skills/gframework-pr-review/SKILL.md`,使其 Git 策略与命令示例都与当前仓库状态一致
- 已把 `DOCUMENTATION-FULL-COVERAGE-GOV-RP-001``RP-007` 的详细验证历史迁入
`ai-plan/public/documentation-full-coverage-governance/archive/todos/documentation-full-coverage-governance-validation-history-through-rp-007.md`
### 当前决策RP-008
- 继续把 latest-head unresolved threads 作为主信号,只修仍在本地成立的评论,不为已失效的历史 summary 做无意义回写
- active tracking 只保留最新验证摘要与恢复点;详细验证历史留在 topic 自己的 archive而不是继续堆在默认 boot 路径
- `gframework-pr-review` 的脚本行为、技能文案与 `AGENTS.md` 必须保持同一套 WSL Git 策略,避免再次出现“文档说法正确但工具实现仍跑偏”的情况
### 当前验证RP-008
- PR review 抓取:
- `python3 .agents/skills/gframework-pr-review/scripts/fetch_current_pr_review.py --json-output /tmp/gframework-current-pr-review.json`:通过
- 脚本语法校验:
- `python3 -B -c "from pathlib import Path; compile(Path('.agents/skills/gframework-pr-review/scripts/fetch_current_pr_review.py').read_text(encoding='utf-8'), '.agents/skills/gframework-pr-review/scripts/fetch_current_pr_review.py', 'exec')"`:通过
- 文档校验:
- `validate-all.sh docs/zh-CN/source-generators/cqrs-handler-registry-generator.md`:通过
- `validate-all.sh docs/zh-CN/ecs/index.md`:通过
- `validate-all.sh docs/zh-CN/abstractions/ecs-arch-abstractions.md`:通过
- 构建校验:
- `cd docs && bun run build`:通过;仅保留既有 VitePress 大 chunk warning无构建失败
### 下一步
1. 提交本轮 PR review follow-up
2. 推送当前分支后重新执行 `$gframework-pr-review`,观察 PR #271 的 open threads 是否收敛

View File

@ -252,6 +252,7 @@ export default defineConfig({
{ text: 'ContextAware 生成器', link: '/zh-CN/source-generators/context-aware-generator' },
{ text: 'Priority 生成器', link: '/zh-CN/source-generators/priority-generator' },
{ text: 'Context Get 注入', link: '/zh-CN/source-generators/context-get-generator' },
{ text: 'CQRS Handler Registry', link: '/zh-CN/source-generators/cqrs-handler-registry-generator' },
{ text: 'Godot 项目元数据', link: '/zh-CN/source-generators/godot-project-generator' },
{ text: 'GetNode 生成器 (Godot)', link: '/zh-CN/source-generators/get-node-generator' },
{ text: 'BindNodeSignal 生成器 (Godot)', link: '/zh-CN/source-generators/bind-node-signal-generator' }
@ -264,7 +265,8 @@ export default defineConfig({
text: '抽象接口',
items: [
{ text: 'Core Abstractions', link: '/zh-CN/abstractions/core-abstractions' },
{ text: 'Game Abstractions', link: '/zh-CN/abstractions/game-abstractions' }
{ text: 'Game Abstractions', link: '/zh-CN/abstractions/game-abstractions' },
{ text: 'Ecs.Arch Abstractions', link: '/zh-CN/abstractions/ecs-arch-abstractions' }
]
}
],

View File

@ -1,192 +1,104 @@
---
title: Core Abstractions
description: GFramework.Core.Abstractions 的契约边界、包关系与 XML 阅读重点。
---
# Core Abstractions
> GFramework.Core.Abstractions 核心抽象接口定义
`GFramework.Core.Abstractions``Core` 运行时的契约包。
## 概述
它负责定义架构、生命周期、事件、状态、资源、日志、配置、并发和持久化相关的接口、枚举和值对象,用来建立跨模块协作边界;
默认实现、基类、容器适配和运行时装配则在 `GFramework.Core` 中。
GFramework.Core.Abstractions 包含了框架的所有核心接口定义,这些接口定义了组件之间的契约,实现了依赖倒置和面向接口编程
如果你要开箱即用地使用框架能力,应依赖 `GFramework.Core`;如果你在做扩展包、测试替身、工具层或多模块拆分,才单独消费本包
## 核心接口
## 什么时候单独依赖它
### IArchitecture
- 你在写插件、模块扩展或测试替身,只想依赖接口而不拉入默认运行时
- 你需要让多个程序集共享架构、状态、资源或日志契约
- 你希望把公共边界放进 `*.Abstractions`,而把具体实现留在应用层或宿主层
应用程序架构接口:
## 包关系
- 契约层:`GFramework.Core.Abstractions`
- 运行时实现:`GFramework.Core`
- 常见相邻契约:`GFramework.Cqrs.Abstractions``GFramework.Game.Abstractions`
## 契约地图
| 契约族 | 作用 |
| --- | --- |
| `Architectures/` `Lifecycle/` `Registries/` | `IArchitecture`、上下文、模块、服务模块、阶段监听、注册表与初始化 / 销毁生命周期契约 |
| `Bases/` `Controller/` `Model/` `Systems/` `Utility/` `Rule/` | 组件角色接口、优先级 / key 值对象、上下文感知边界 |
| `Command/` `Query/` `Cqrs/` | 旧版命令 / 查询执行器接口,以及与新版请求模型衔接的运行时契约 |
| `Events/` `Property/` `State/` `StateManagement/` | 事件总线、解绑对象、可绑定属性、状态机、Store / reducer / middleware 契约 |
| `Coroutine/` `Time/` `Pause/` `Concurrency/` | 协程状态、时间源、暂停栈、键控异步锁与统计对象 |
| `Resource/` `Pool/` `Logging/` `Localization/` | 资源句柄、对象池、日志、logger factory、本地化表与格式化契约 |
| `Configuration/` `Environment/` | 配置管理器、环境对象与运行时环境访问契约 |
| `Data/` `Serializer/` `Storage/` `Versioning/` | 数据装载、序列化、存储与版本化契约 |
| `Enums/` `Properties/` | 架构阶段枚举,以及架构 / logger 相关属性键 |
## 最小接入路径
### 1. 只面向契约编程
```csharp
public interface IArchitecture
{
void Initialize();
void Destroy();
T GetModel<T>() where T : IModel;
T GetSystem<T>() where T : ISystem;
T GetUtility<T>() where T : IUtility;
void RegisterModel(IModel model);
void RegisterSystem(ISystem system);
void RegisterUtility(IUtility utility);
}
```
using GFramework.Core.Abstractions.Architectures;
using GFramework.Core.Abstractions.Logging;
### IModel
数据模型接口:
```csharp
public interface IModel
{
void Init();
void Dispose();
IArchitecture Architecture { get; }
}
```
### ISystem
业务逻辑系统接口:
```csharp
public interface ISystem
{
void Init();
void Dispose();
IArchitecture Architecture { get; }
}
```
### IController
控制器接口:
```csharp
public interface IController : IBelongToArchitecture
{
void Init();
void Dispose();
}
```
### IUtility
工具类接口:
```csharp
public interface IUtility
{
}
```
## 事件接口
### IEvent
事件基接口:
```csharp
public interface IEvent
{
}
```
### IEventHandler
事件处理器接口:
```csharp
public interface IEventHandler<TEvent> where TEvent : IEvent
{
void Handle(TEvent @event);
}
```
## 命令查询接口
### ICommand
命令接口:
```csharp
public interface ICommand
{
void Execute();
}
```
### IQuery
查询接口:
```csharp
public interface IQuery<TResult>
{
TResult Execute();
}
```
## 依赖注入接口
### IIocContainer
IoC 容器接口:
```csharp
public interface IIocContainer
{
void Register<TInterface, TImplementation>() where TImplementation : TInterface;
void Register<TInterface>(TInterface instance);
TInterface Resolve<TInterface>();
bool IsRegistered<TInterface>();
}
```
## 生命周期接口
### ILifecycle
组件生命周期接口:
```csharp
public interface ILifecycle
{
void OnInit();
void OnDestroy();
}
```
## 使用示例
### 通过接口实现依赖注入
```csharp
public class MyService : IMyService
public sealed class DiagnosticsFeature
{
private readonly IArchitecture _architecture;
public MyService(IArchitecture architecture)
private readonly ILogger _logger;
public DiagnosticsFeature(IArchitecture architecture, ILogger logger)
{
_architecture = architecture;
_logger = logger;
}
}
```
### 自定义事件
### 2. 什么时候切到运行时包
```csharp
public class PlayerDiedEvent : IEvent
{
public int PlayerId { get; set; }
public Vector2 Position { get; set; }
}
```
下面这些需求都属于 `GFramework.Core` 的职责,而不是本包:
---
- 继承 `Architecture` 并完成默认初始化流程
- 使用 `ContextAwareBase``AbstractModel``AbstractSystem` 等默认基类
- 使用默认的 `CommandExecutor``QueryExecutor``BindableProperty<T>``StateMachine`
- 直接启用默认的 `Microsoft.Extensions.DependencyInjection` 容器适配或资源 / 协程 / 日志实现
**相关文档**
## XML 阅读重点
- [Core 概述](../core/index.md)
- [Architecture](../core/architecture)
- [Events](../core/events)
- [Command](../core/command)
- [Query](../core/query)
如果你在做契约审计、采用设计或扩展适配,优先核对这些类型族的 XML 文档:
- 架构与模块入口:`IArchitecture``IArchitectureContext``IServiceModule`
- 运行时基础设施:`IIocContainer``ILogger``IResourceManager``IConfigurationManager`
- 状态与并发能力:`IStateMachine``IStore``IAsyncKeyLockManager``ITimeProvider`
- 迁移与组合边界:`ICommandExecutor``IQueryExecutor``ICqrsRuntime`
## XML 覆盖基线
下面这份 inventory 记录的是 `2026-04-22``GFramework.Core.Abstractions` 做的一轮轻量 XML 盘点结果:只统计公开 /
内部类型声明是否带 XML 注释,用来建立契约层阅读入口;成员级参数、返回值、异常与生命周期说明仍需要后续波次继续细化。
| 契约族 | 基线状态 | 代表类型 | 阅读重点 |
| --- | --- | --- | --- |
| `Architectures/` | `12/12` 个类型声明已带 XML 注释 | `IArchitecture``IArchitectureContext``IArchitectureServices``IServiceModule` | 看架构上下文、服务访问面与模块安装 / 生命周期约束 |
| `Lifecycle/` `Registries/` | `8/8` 个类型声明已带 XML 注释 | `ILifecycle``IAsyncInitializable``IRegistry<T, TR>``KeyValueRegistryBase<TKey, TValue>` | 看初始化 / 销毁阶段和注册表抽象边界 |
| `Command/` `Query/` `Cqrs/` | `10/10` 个类型声明已带 XML 注释 | `ICommandExecutor``IAsyncCommand<TResult>``IQueryExecutor``ICqrsRuntime` | 看旧命令 / 查询接口与新请求模型之间的兼容和迁移边界 |
| `Events/` `Property/` | `10/10` 个类型声明已带 XML 注释 | `IEventBus``IEventFilter<T>``IBindableProperty<T>``IReadonlyBindableProperty<T>` | 看事件传播、过滤、解绑对象和属性订阅语义 |
| `State/` `StateManagement/` | `15/15` 个类型声明已带 XML 注释 | `IStateMachine``IAsyncState``IStore<TState>``IStoreMiddleware<TState>` | 看状态机契约与 Store 的 reducer / middleware / diagnostics 边界 |
| `Coroutine/` `Time/` `Pause/` `Concurrency/` | `17/17` 个类型声明已带 XML 注释 | `IYieldInstruction``ICoroutineStatistics``ITimeProvider``IPauseStackManager``IAsyncKeyLockManager` | 看调度模型、时间源、暂停栈和异步锁契约 |
| `Resource/` `Pool/` `Logging/` `Localization/` | `27/27` 个类型声明已带 XML 注释 | `IResourceManager``IObjectPoolSystem``ILogger``IStructuredLogger``ILocalizationManager` | 看资源 / 池化 / 日志 / 本地化这些基础设施的宿主责任 |
| `Configuration/` `Environment/` `Data/` `Serializer/` `Storage/` `Versioning/` | `7/7` 个类型声明已带 XML 注释 | `IConfigurationManager``IEnvironment``ILoadableFrom<T>``ISerializer``IStorage``IVersioned` | 看配置、环境、序列化和持久化边界,以及谁负责具体实现 |
| `Bases/` `Controller/` `Model/` `Systems/` `Utility/` `Rule/` `Enums/` `Properties/` | `19/19` 个类型声明已带 XML 注释 | `IPrioritized``IController``IModel``ISystem``IContextUtility``ArchitecturePhase` | 看基础角色接口、辅助值对象和架构属性键的复用方式 |
## 阅读顺序
1. 先读本页,确认你是否真的只需要契约层
2. 再看 [`../core/index.md`](../core/index.md) 了解默认运行时怎么组织这些契约
3. 回到模块 README
- `GFramework.Core.Abstractions/README.md`
- `GFramework.Core/README.md`
4. 需要统一导航时,再看 [`../api-reference/index.md`](../api-reference/index.md)

View File

@ -0,0 +1,94 @@
---
title: Ecs.Arch Abstractions
description: GFramework.Ecs.Arch.Abstractions 的契约边界、包关系和最小接入路径。
---
# Ecs.Arch Abstractions
`GFramework.Ecs.Arch.Abstractions` 是 Arch ECS 集成层的契约包。
它建立在 `GFramework.Core.Abstractions` 之上,只定义 ECS 模块更新、系统适配和配置对象,不负责默认的 Arch
`World` 装配、扩展方法或系统基类。
如果你需要开箱即用的集成实现,请改为依赖 `GFramework.Ecs.Arch`
## 什么时候单独依赖它
- 你在做共享宿主循环、工具层或 feature 包,只需要 `IArchEcsModule`
- 你想让不同程序集共享 `ArchOptions` 或系统适配契约,但不直接绑定默认 runtime
- 你需要为测试或外部适配层提供替身实现
## 包关系
- 契约层:`GFramework.Ecs.Arch.Abstractions`
- 运行时实现:`GFramework.Ecs.Arch`
- 底层基础契约:`GFramework.Core.Abstractions`
## 契约地图
| 类型 | 作用 |
| --- | --- |
| `IArchEcsModule` | 统一更新 ECS 系统的服务模块契约 |
| `IArchSystemAdapter<T>` | 让 ECS 系统适配到 `ISystem` 生命周期 |
| `ArchOptions` | 承载 `WorldCapacity``EnableStatistics``Priority` 等配置 |
## 类型族级 XML Inventory
| 类型族 | 代表类型 | XML 状态 | 阅读重点 |
| --- | --- | --- | --- |
| 模块契约 | `IArchEcsModule` | 已覆盖 | 统一更新入口、宿主循环边界 |
| 系统契约 | `IArchSystemAdapter<T>` | 已覆盖 | 只依赖更新接口而不绑定默认 runtime |
| 配置对象 | `ArchOptions` | 已覆盖 | 共享配置字段与跨程序集采用边界 |
## 最小接入路径
### 1. 共享模块只依赖更新契约
```csharp
using GFramework.Ecs.Arch.Abstractions;
public sealed class GameplayHost
{
private readonly IArchEcsModule _ecsModule;
public GameplayHost(IArchEcsModule ecsModule)
{
_ecsModule = ecsModule;
}
public void Tick(float deltaTime)
{
_ecsModule.Update(deltaTime);
}
}
```
### 2. 共享配置对象
```csharp
using GFramework.Ecs.Arch.Abstractions;
var options = new ArchOptions
{
WorldCapacity = 2048,
EnableStatistics = true,
Priority = 40
};
```
### 3. 什么时候切到运行时包
下面这些需求都属于 `GFramework.Ecs.Arch` 的职责,而不是本包:
- 通过 `UseArch(...)` 把模块挂进架构
- 使用默认的 `ArchSystemAdapter<T>` 基类
- 访问 Arch `World` 与查询 API
- 使用默认的模块装配和生命周期实现
## 阅读顺序
1. 先读本页,确认你是否真的只需要契约层
2. 如果需要默认实现,再看 [`../ecs/arch.md`](../ecs/arch.md)
3. 回到对应模块 README
- `GFramework.Ecs.Arch.Abstractions/README.md`
- `GFramework.Ecs.Arch/README.md`

View File

@ -1,94 +1,122 @@
# Game Abstractions
> GFramework.Game.Abstractions 游戏模块抽象接口定义
## 概述
GFramework.Game.Abstractions 包含了游戏特定功能的抽象接口,这些接口定义了游戏开发中的通用契约。
## 存档接口
### ISaveSystem
存档系统接口:
```csharp
public interface ISaveSystem
{
void Save(string slotId, SaveData data);
SaveData Load(string slotId);
bool HasSave(string slotId);
void Delete(string slotId);
List<SaveSlotInfo> GetAllSaveSlots();
}
```
### ISaveData
存档数据接口:
```csharp
public interface ISaveData
{
int Version { get; }
DateTime Timestamp { get; }
void Validate();
}
```
## 设置接口
### IGameSettings
游戏设置接口:
```csharp
public interface IGameSettings
{
AudioSettings Audio { get; }
GraphicsSettings Graphics { get; }
InputSettings Input { get; }
void Save();
void Load();
void ResetToDefaults();
}
```
## 场景管理接口
### ISceneManager
场景管理器接口:
```csharp
public interface ISceneManager
{
void SwitchScene<TScene>() where TScene : IScene;
Task SwitchSceneAsync<TScene>() where TScene : IScene;
void PushScene<TScene>() where TScene : IScene;
void PopScene();
IScene CurrentScene { get; }
}
```
### IScene
场景接口:
```csharp
public interface IScene
{
void OnEnter();
void OnExit();
void OnUpdate(float delta);
}
```
---
title: Game Abstractions
description: GFramework.Game.Abstractions 的契约边界、包关系与 XML 阅读重点。
---
**相关文档**
# Game Abstractions
- [Game 概述](../game/index.md)
- [核心抽象](./core-abstractions.md)
`GFramework.Game.Abstractions``Game` 运行时的契约包。
它建立在 `GFramework.Core.Abstractions` 之上负责定义配置、数据、设置、场景、UI、路由、存储和资源注册表相关的接口、
枚举与事件契约默认实现、路由基类、YAML 加载器、文件存储和设置 / 存档仓库则在 `GFramework.Game` 中。
如果你要开箱即用地接入游戏运行时能力,应依赖 `GFramework.Game`如果你在做共享业务层、feature 包、测试替身或引擎适配层,
才单独消费本包。
## 什么时候单独依赖它
- 你希望公共业务层只依赖 `ISceneRouter``IUiRouter``ISettingsSystem``ISaveRepository<TSaveData>` 这类契约
- 你要让多个程序集共享 `ISettingsData``IData``ISceneEnterParam``IUiPageEnterParam` 等数据和路由上下文
- 你需要自己实现 factory、root、存储或配置加载器但不想把默认运行时一起带进来
## 包关系
- 契约层:`GFramework.Game.Abstractions`
- 运行时实现:`GFramework.Game`
- 底层基础契约:`GFramework.Core.Abstractions`
## 契约地图
| 契约族 | 作用 |
| --- | --- |
| `Config/` | `IConfigLoader``IConfigRegistry``IConfigTable<TKey, TValue>` 和配置失败诊断模型 |
| `Data/` | `IData``IVersionedData``IDataRepository``ISettingsDataRepository``ISaveRepository<TSaveData>` 及数据事件 |
| `Setting/` | `ISettingsData``ISettingsModel``ISettingsSystem`、设置迁移契约与内置设置数据类型 |
| `Scene/` | `IScene``ISceneRouter``ISceneFactory``ISceneRoot`、转场处理器与事件 |
| `UI/` | `IUiPage``IUiRouter``IUiFactory``IUiRoot`、交互配置与 UI 转场选项 |
| `Routing/` | `IRoute``IRouteContext``IRouteGuard<TRoute>`,作为 Scene / UI 共享的路由基础约定 |
| `Storage/` `Asset/` `Enums/` | 文件存储角色、资源注册表,以及转场 / UI 层级 / 输入动作等跨层枚举 |
## XML 覆盖基线
下面这份 inventory 记录的是 `2026-04-23``GFramework.Game.Abstractions` 做的一轮轻量 XML 盘点结果:只统计公开 /
内部类型声明是否带 XML 注释,用来建立契约层阅读入口;成员级参数、返回值、异常和生命周期说明仍需要后续 API 波次继续细化。
| 契约族 | 基线状态 | 代表类型 | 阅读重点 |
| --- | --- | --- | --- |
| `Config/` | `7/7` 个类型声明已带 XML 注释 | `IConfigLoader``IConfigRegistry``IConfigTable<TKey, TValue>``ConfigLoadException` | 看配置表注册、只读访问和失败诊断边界 |
| `Data/` | `14/14` 个类型声明已带 XML 注释 | `IDataRepository``ISettingsDataRepository``ISaveRepository<TSaveData>``DataRepositoryOptions` | 看业务数据、统一设置文件、槽位存档与迁移契约 |
| `Setting/` | `12/12` 个类型声明已带 XML 注释 | `ISettingsData``ISettingsModel``ISettingsSystem``LocalizationSettings` | 看设置生命周期、应用语义、迁移接口和内置设置对象 |
| `Scene/` | `14/14` 个类型声明已带 XML 注释 | `IScene``ISceneRouter``ISceneFactory``SceneTransitionEvent` | 看场景行为、工厂 / root 边界和转场模型 |
| `UI/` | `19/19` 个类型声明已带 XML 注释 | `IUiPage``IUiRouter``IUiFactory``UiInteractionProfile``UiTransitionHandlerOptions` | 看页面栈、层级 UI、输入动作和 UI 转场契约 |
| `Routing/` `Storage/` `Asset/` `Enums/` | `13/13` 个类型声明已带 XML 注释 | `IRoute``IRouteContext``IFileStorage``IAssetRegistry<T>``UiLayer``SceneTransitionType` | 看公共路由上下文、存储角色、资源注册表与共享枚举 |
## 最小接入路径
### 1. 只在公共业务层声明游戏对象
```csharp
using GFramework.Game.Abstractions.Data;
using GFramework.Game.Abstractions.Scene;
using GFramework.Game.Abstractions.UI;
public sealed class GameSaveData : IVersionedData
{
public int Version { get; set; } = 1;
public DateTime LastModified { get; set; } = DateTime.UtcNow;
}
public sealed class GameplayEnterParam : ISceneEnterParam
{
public required string Seed { get; init; }
}
public sealed class PauseMenuParam : IUiPageEnterParam
{
public bool AllowRestart { get; init; }
}
```
### 2. 让 feature 包只依赖抽象
```csharp
using GFramework.Game.Abstractions.Data;
using GFramework.Game.Abstractions.Scene;
public sealed class ContinueGameCommandHandler
{
private readonly ISaveRepository<GameSaveData> _saveRepository;
private readonly ISceneRouter _sceneRouter;
public ContinueGameCommandHandler(
ISaveRepository<GameSaveData> saveRepository,
ISceneRouter sceneRouter)
{
_saveRepository = saveRepository;
_sceneRouter = sceneRouter;
}
}
```
### 3. 什么时候切到运行时包
下面这些需求都属于 `GFramework.Game` 的职责,而不是本包:
- 使用默认的 `JsonSerializer``FileStorage``ScopedStorage`
- 使用 `SettingsModel<TRepository>``SettingsSystem``SaveRepository<TSaveData>` 等默认实现
- 使用 `YamlConfigLoader``GameConfigBootstrap``GameConfigModule`
- 继承 `SceneRouterBase``UiRouterBase` 或默认转场处理器基类
## 阅读顺序
1. 先读本页,确认你是否真的只需要契约层
2. 再看 [`../game/index.md`](../game/index.md) 了解默认运行时怎么组织这些契约
3. 继续读具体专题页:
- [`../game/config-system.md`](../game/config-system.md)
- [`../game/data.md`](../game/data.md)
- [`../game/setting.md`](../game/setting.md)
- [`../game/scene.md`](../game/scene.md)
- [`../game/ui.md`](../game/ui.md)
4. 需要仓库侧入口时,回到:
- `GFramework.Game.Abstractions/README.md`
- `GFramework.Game/README.md`

View File

@ -1,3 +1,8 @@
---
title: 抽象接口
description: GFramework 各抽象层模块的阅读入口与使用边界。
---
# 抽象接口
`GFramework.*.Abstractions` 用来承载跨模块协作所需的契约,而不是运行时实现。
@ -12,9 +17,19 @@
- Core 抽象层:[`core-abstractions.md`](./core-abstractions.md)
- Game 抽象层:[`game-abstractions.md`](./game-abstractions.md)
- Ecs.Arch 抽象层:[`ecs-arch-abstractions.md`](./ecs-arch-abstractions.md)
## 使用建议
- 如果你只是想直接使用框架功能,优先从对应运行时模块的 `README.md` 和栏目页开始。
- 只有在明确需要“契约层而非实现层”时,才单独依赖 `*.Abstractions` 包。
- 抽象层页面会解释接口分组与职责;实际安装与接入路径,仍应以运行时模块 README 与 `getting-started` 为主。
- 抽象层页面会解释接口分组与职责;实际安装与接入路径,仍应以运行时模块 README 与 `getting-started` 为主。
## 当前边界
- `GFramework.Core.SourceGenerators.Abstractions`
- `GFramework.Godot.SourceGenerators.Abstractions`
- `GFramework.SourceGenerators.Common`
这些目录当前不作为独立抽象接口栏目维护,而是作为源码生成器家族的内部支撑模块,分别跟随所属模块 README 和
`source-generators` 栏目维护。

View File

@ -1,571 +1,81 @@
# API 参考文档
本文档提供 GFramework 各模块的完整 API 参考。
## 核心命名空间
### GFramework.Core.architecture
核心架构命名空间,包含所有基础组件。
#### 主要类型
| 类型 | 说明 |
|--------------------|--------|
| `Architecture` | 应用架构基类 |
| `AbstractModel` | 数据模型基类 |
| `AbstractSystem` | 业务系统基类 |
| `AbstractCommand` | 命令基类 |
| `AbstractQuery<T>` | 查询基类 |
| `IController` | 控制器接口 |
| `IUtility` | 工具类接口 |
### GFramework.Core.events
事件系统命名空间。
#### 主要类型
| 类型 | 说明 |
|-------------------|----------|
| `IEvent` | 事件接口 |
| `IEventSystem` | 事件系统接口 |
| `TypeEventSystem` | 类型安全事件系统 |
### GFramework.Core.property
属性系统命名空间。
#### 主要类型
| 类型 | 说明 |
|-----------------------|--------|
| `BindableProperty<T>` | 可绑定属性 |
| `IUnRegister` | 注销接口 |
| `IUnRegisterList` | 注销列表接口 |
### GFramework.Core.ioc
IoC 容器命名空间。
#### 主要类型
| 类型 | 说明 |
|--------------|------|
| `IContainer` | 容器接口 |
| `Container` | 容器实现 |
### GFramework.Core.pool
对象池命名空间。
#### 主要类型
| 类型 | 说明 |
|------------------|-------|
| `IObjectPool<T>` | 对象池接口 |
| `ObjectPool<T>` | 对象池实现 |
### GFramework.Core.Localization
本地化系统命名空间。
#### 主要类型
| 类型 | 说明 |
|--------------------------|----------|
| `ILocalizationManager` | 本地化管理器接口 |
| `ILocalizationTable` | 本地化表接口 |
| `ILocalizationString` | 本地化字符串接口 |
| `ILocalizationFormatter` | 格式化器接口 |
| `LocalizationConfig` | 本地化配置类 |
| `LocalizationManager` | 本地化管理器实现 |
| `LocalizationTable` | 本地化表实现 |
| `LocalizationString` | 本地化字符串实现 |
## 常用 API
### Architecture
```csharp
public abstract class Architecture : IBelongToArchitecture
{
// 初始化架构
public void Initialize();
// 销毁架构
public void Destroy();
// 注册模型
public void RegisterModel<T>(T model) where T : IModel;
// 获取模型
public T GetModel<T>() where T : IModel;
// 注册系统
public void RegisterSystem<T>(T system) where T : ISystem;
// 获取系统
public T GetSystem<T>() where T : ISystem;
// 注册工具
public void RegisterUtility<T>(T utility) where T : IUtility;
// 获取工具
public T GetUt>() where T : IUtility;
// 发送命令
public void SendCommand<T>(T command) where T : ICommand;
// 发送查询
public TResult SendQuery<TQuery, TResult>(TQuery query)
where TQuery : IQuery<TResult>;
// 发送事件
public void SendEvent<T>(T e) where T : IEvent;
}
```
### AbstractModel
```csharp
public abstract class AbstractModel : IBelongToArchitecture
{
// 初始化模型
protected abstract void OnInit();
// 销毁模型
protected virtual void OnDestroy();
// 获取架构
public IArchitecture GetArchitecture();
// 发送事件
protected void SendEvent<T>(T e) where T : IEvent;
// 获取模型
protected T GetModel<T>() where T : IModel;
// 获取系统
protected T GetSystem<T>() where T : ISystem;
// 获取工具
protected T GetUtility<T>() where T : IUtility;
}
```
### AbstractSystem
```csharp
public abstract class AbstractSystem : IBelongToArchitecture
{
// 初始化系统
protected abstract void OnInit();
// 销毁系统
protected virtual void OnDestroy();
// 获取架构
public IArchitecture GetArchitecture();
// 发送事件
protected void SendEvent<T>(T e) where T : IEvent;
// 注册事件
protected IUnRegister RegisterEvent<T>(Action<T> onEvent)
where T : IEvent;
// 获取模型
protected T GetModel<T>() where T : IModel;
// 获取系统
protected T GetSystem<T>() where T : ISystem;
// 获取工具
protected T GetUtility<T>() where T : IUtility;
}
```
### AbstractCommand
```csharp
public abstract class AbstractCommand : IBelongToArchitecture
{
// 执行命令
public void Execute();
// 命令实现
protected abstract void OnDo();
// 获取架构
public IArchitecture GetArchitecture();
// 发送事件
protected void SendEvent<T>(T e) where T : IEvent;
// 获取模型
protected T GetModel<T>() where T : IModel;
// 获取系统
protected T GetSystem<T>() where T : ISystem;
// 获取工具
protected T GetUtility<T>() where T : IUtility;
}
```
### AbstractQuery`<T>`
```csharp
public abstract class AbstractQuery<T> : IBelongToArchitecture
{
// 执行查询
public T Do();
// 查询实现
protected abstract T OnDo();
// 获取架构
public IArchitecture GetArchitecture();
// 获取模型
protected T GetModel<T>() where T : IModel;
// 获取系统
protected T GetSystem<T>() where T : ISystem;
// 获取工具
protected T GetUtility<T>() where T : IUtility;
}
```
### BindableProperty`<T>`
```csharp
public class BindableProperty<T>
{
// 构造函数
public BindableProperty(T initialValue = default);
// 获取或设置值
public T Value { get; set; }
// 注册监听器
public IUnRegister Register(Action<T> onValueChanged);
// 注册监听器(包含初始值)
public IUnRegister RegisterWithInitValue(Action<T> onValueChanged);
// 获取当前值
public T GetValue();
// 设置值
public void SetValue(T newValue);
}
```
### ILocalizationManager
```csharp
public interface ILocalizationManager : ISystem
{
// 获取当前语言代码
string CurrentLanguage { get; }
// 获取当前文化信息
CultureInfo CurrentCulture { get; }
// 获取可用语言列表
IReadOnlyList<string> AvailableLanguages { get; }
// 设置当前语言
void SetLanguage(string languageCode);
// 获取本地化表
ILocalizationTable GetTable(string tableName);
// 获取本地化文本
string GetText(string table, string key);
// 获取本地化字符串(支持变量)
ILocalizationString GetString(string table, string key);
// 尝试获取本地化文本
bool TryGetText(string table, string key, out string text);
// 注册格式化器
void RegisterFormatter(string name, ILocalizationFormatter formatter);
// 订阅语言变化事件
void SubscribeToLanguageChange(Action<string> callback);
// 取消订阅语言变化事件
void UnsubscribeFromLanguageChange(Action<string> callback);
}
```
### ILocalizationString
```csharp
public interface ILocalizationString
{
// 获取表名
string Table { get; }
// 获取键名
string Key { get; }
// 添加变量
ILocalizationString WithVariable(string name, object value);
// 批量添加变量
ILocalizationString WithVariables(params (string name, object value)[] variables);
// 格式化并返回文本
string Format();
// 获取原始文本
string GetRaw();
// 检查键是否存在
bool Exists();
}
```
### LocalizationConfig
```csharp
public class LocalizationConfig
{
// 默认语言代码
public string DefaultLanguage { get; set; } = "eng";
// 回退语言代码
public string FallbackLanguage { get; set; } = "eng";
// 本地化文件路径
public string LocalizationPath { get; set; } = "res://localization";
// 用户覆盖路径
public string OverridePath { get; set; } = "user://localization_override";
// 是否启用热重载
public bool EnableHotReload { get; set; } = true;
// 是否在加载时验证
public bool ValidateOnLoad { get; set; } = true;
}
```
## 扩展方法
### 架构扩展
```csharp
// 发送命令
public static void SendCommand<T>(this IBelongToArchitecture self, T command)
where T : ICommand;
// 发送查询
public static TResult SendQuery<TQuery, TResult>(
this IBelongToArchitecture self, TQuery query)
where TQuery : IQuery<TResult>;
// 发送事件
public static void SendEvent<T>(this IBelongToArchitecture self, T e)
where T : IEvent;
// 获取模型
public static T GetModel<T>(this IBelongToArchitecture self)
where T : IModel;
// 获取系统
public static T GetSystem<T>(this IBelongToArchitecture self)
where T : ISystem;
// 获取工具
public static T GetUtility<T>(this IBelongToArchitecture self)
where T : IUtility;
// 注册事件
public static IUnRegister RegisterEvent<T>(
this IBelongToArchitecture self, Action<T> onEvent)
where T : IEvent;
```
### 属性扩展
```csharp
// 添加到注销列表
public static IUnRegister AddToUnregisterList(
this IUnRegister self, IUnRegisterList list);
// 注销所有
public static void UnRegisterAll(this IUnRegisterList self);
```
## 游戏模块 API
### GFramework.Game
游戏业务扩展模块。
#### 主要类型
| 类型 | 说明 |
|---------------|--------|
| `GameSetting` | 游戏设置 |
| `GameState` | 游戏状态 |
| `IGameModule` | 游戏模块接口 |
## Godot 集成 API
### GFramework.Godot
Godot 引擎集成模块。
#### 主要类型
| 类型 | 说明 |
|------------------|------------|
| `GodotNode` | Godot 节点扩展 |
| `GodotCoroutine` | Godot 协程 |
| `GodotSignal` | Godot 信号 |
## 源码生成器
### Source Generators 家族
自动代码生成工具按模块拆分为 `GFramework.Core.SourceGenerators``GFramework.Game.SourceGenerators`
`GFramework.Godot.SourceGenerators``GFramework.Cqrs.SourceGenerators`。面向业务代码声明的 Attribute
主要来自 `GFramework.Core.SourceGenerators.Abstractions.*` 与对应模块的 runtime/generator 包。
#### 支持的生成器
| 生成器 | 说明 |
|--------------------------------------------|-------------|
| `LoggingGenerator` | 日志生成器 |
| `EnumGenerator` | 枚举扩展生成器 |
| `RuleGenerator` | 规则生成器 |
| `AutoRegisterModuleGenerator` | 架构模块注册生成器 |
| `AutoUiPageGenerator` | UI 页面行为生成器 |
| `AutoSceneGenerator` | 场景行为生成器 |
| `AutoRegisterExportedCollectionsGenerator` | 导出集合批量注册生成器 |
#### 常用 Attribute
| Attribute | 说明 | 文档 |
|--------------------------------------------|-------------------------------------------|-------------------------------------------------------------------------------------------------------------|
| `AutoRegisterModuleAttribute` | 为模块类生成 `Install(IArchitecture)` | [AutoRegisterModule 生成器](../source-generators/auto-register-module-generator.md) |
| `RegisterModelAttribute` | 声明模块内自动注册的 `IModel` 类型 | [AutoRegisterModule 生成器](../source-generators/auto-register-module-generator.md) |
| `RegisterSystemAttribute` | 声明模块内自动注册的 `ISystem` 类型 | [AutoRegisterModule 生成器](../source-generators/auto-register-module-generator.md) |
| `RegisterUtilityAttribute` | 声明模块内自动注册的 `IUtility` 类型 | [AutoRegisterModule 生成器](../source-generators/auto-register-module-generator.md) |
| `AutoUiPageAttribute` | 为 `CanvasItem` 页面节点生成 `GetPage()` | [AutoUiPage 生成器](../source-generators/auto-ui-page-generator.md) |
| `AutoSceneAttribute` | 为场景根节点生成 `GetScene()` | [AutoScene 生成器](../source-generators/auto-scene-generator.md) |
| `AutoLoadAttribute` | 显式声明 `project.godot` AutoLoad 与 C# 节点类型映射 | [Godot 项目元数据生成器](../source-generators/godot-project-generator.md) |
| `AutoRegisterExportedCollectionsAttribute` | 为宿主类开启导出集合批量注册生成 | [AutoRegisterExportedCollections 生成器](../source-generators/auto-register-exported-collections-generator.md) |
| `RegisterExportedCollectionAttribute` | 指定集合与注册器成员的映射关系 | [AutoRegisterExportedCollections 生成器](../source-generators/auto-register-exported-collections-generator.md) |
## 常见用法示例
### 创建架构
```csharp
public class MyArchitecture : Architecture
{
protected override void Init()
{
RegisterModel(new PlayerModel());
RegisterSystem(new PlayerSystem());
RegisterUtility(new StorageUtility());
}
}
// 使用
var arch = new MyArchitecture();
arch.Initialize();
```
### 发送命令
```csharp
public class AttackCommand : AbstractCommand
{
public int Damage { get; set; }
protected override void OnDo()
{
var player = this.GetModel<PlayerModel>();
this.SendEvent(new AttackEvent { Damage = Damage });
}
}
// 使用
arch.SendCommand(new AttackCommand { Damage = 10 });
```
### 发送查询
```csharp
public class GetPlayerHealthQuery : AbstractQuery<int>
{
protected override int OnDo()
{
return this.GetModel<PlayerModel>().Health.Value;
}
}
// 使用
var health = arch.SendQuery(new GetPlayerHealthQuery());
```
### 监听事件
```csharp
public class PlayerSystem : AbstractSystem
{
protected override void OnInit()
{
this.RegisterEvent<PlayerDiedEvent>(OnPlayerDied);
}
private void OnPlayerDied(PlayerDiedEvent e)
{
Console.WriteLine("Player died!");
}
}
```
### 使用本地化
```csharp
// 初始化本地化管理器
var config = new LocalizationConfig
{
DefaultLanguage = "eng",
LocalizationPath = "res://localization"
};
var locManager = new LocalizationManager(config);
locManager.Initialize();
// 获取简单文本
string title = locManager.GetText("common", "game.title");
// 使用变量
var message = locManager.GetString("common", "ui.message.welcome")
.WithVariable("playerName", "Alice")
.Format();
// 切换语言
locManager.SetLanguage("zhs");
// 监听语言变化
locManager.SubscribeToLanguageChange(language =>
{
Console.WriteLine($"Language changed to: {language}");
});
```
---
title: API 参考
description: GFramework 的 API 阅读入口,按模块映射 README、专题页、XML 文档和教程链路。
---
更多详情请查看各模块的详细文档。
# API 参考
这里不再维护一份脱离源码演化的“伪 API 列表”。
当前 `GFramework` 的 API 参考链路以四类证据协同为准:
1. 模块 README说明包关系、最小接入路径和目录边界
2. `docs/zh-CN` 专题页:说明采用顺序、生命周期和使用建议
3. 代码中的 XML 文档:说明公开 / 内部类型和关键成员的契约
4. 教程页:说明这些 API 在真实接入路径中的组合方式
## 阅读顺序
### 想确认“该装哪个包、先看哪类 API”
先读模块 README再读对应 landing page
- 入门入口:[`../getting-started/index.md`](../getting-started/index.md)
- 根模块地图:仓库根 `README.md`
### 想确认“这个功能属于哪个模块”
按下面的模块映射进入对应入口:
| 模块族 | 模块 README | 站内入口 | XML 文档关注点 |
| --- | --- | --- | --- |
| `Core` / `Core.Abstractions` | `GFramework.Core/README.md``GFramework.Core.Abstractions/README.md` | [`../core/index.md`](../core/index.md)、[`../abstractions/core-abstractions.md`](../abstractions/core-abstractions.md) | 架构入口、生命周期、命令 / 查询 / 事件 / 状态 / 资源 / 日志 / 配置 / 并发契约 |
| `Cqrs` / `Cqrs.Abstractions` / `Cqrs.SourceGenerators` | `GFramework.Cqrs/README.md``GFramework.Cqrs.Abstractions/README.md``GFramework.Cqrs.SourceGenerators/README.md` | [`../core/cqrs.md`](../core/cqrs.md)、[`../source-generators/cqrs-handler-registry-generator.md`](../source-generators/cqrs-handler-registry-generator.md) | request / notification / handler / pipeline / registry / fallback contract |
| `Game` / `Game.Abstractions` / `Game.SourceGenerators` | `GFramework.Game/README.md``GFramework.Game.Abstractions/README.md``GFramework.Game.SourceGenerators/README.md` | [`../game/index.md`](../game/index.md)、[`../abstractions/game-abstractions.md`](../abstractions/game-abstractions.md) | 配置、数据、设置、场景、UI、存储、序列化契约 |
| `Godot` / `Godot.SourceGenerators` | `GFramework.Godot/README.md``GFramework.Godot.SourceGenerators/README.md` | [`../godot/index.md`](../godot/index.md)、[`../source-generators/index.md`](../source-generators/index.md) | 节点扩展、场景 / UI 适配、资源 / 存储 / 日志接入 |
| `Ecs.Arch` / `Ecs.Arch.Abstractions` | `GFramework.Ecs.Arch/README.md``GFramework.Ecs.Arch.Abstractions/README.md` | [`../ecs/index.md`](../ecs/index.md)、[`../ecs/arch.md`](../ecs/arch.md)、[`../abstractions/ecs-arch-abstractions.md`](../abstractions/ecs-arch-abstractions.md) | ECS 模块契约、系统适配、配置对象和运行时装配边界 |
## 先看 XML还是先看教程
### 先看 XML 文档的情况
- 你在确认公开类型的约束、线程 / 生命周期语义、参数和返回值契约
- 你需要区分“抽象层保证了什么”和“默认实现额外提供了什么”
- 你在做多模块拆分、测试替身或扩展适配层
优先关注这些类型族:
- 架构 / 模块 / 服务入口
- 生命周期、注册、路由、工厂、provider 契约
- Source Generator 的 attribute、diagnostic 和 generated contract
### 先看教程和专题页的情况
- 你要的是最小接入路径,而不是逐个类型审计
- 你想确认模块组合方式、目录约定和推荐接线顺序
- 你在做从旧入口迁移到新入口的采用决策
优先入口:
- 教程概览:[`../tutorials/index.md`](../tutorials/index.md)
- 最佳实践:[`../best-practices/index.md`](../best-practices/index.md)
- 故障排查:[`../troubleshooting.md`](../troubleshooting.md)
## 当前边界
- `GFramework.Core.SourceGenerators.Abstractions`
- `GFramework.Godot.SourceGenerators.Abstractions`
- `GFramework.SourceGenerators.Common`
这些目录当前不是独立消费模块,因此不单独维护站内 API 参考入口。它们的公开说明跟随所属模块 README 和
`source-generators` 栏目维护。
## 使用方式
把本页当成“API 阅读导航”而不是“签名快照”:
- 先选模块
- 再进 README 和专题页确认采用路径
- 最后回到代码里的 XML 文档核对具体契约
当 README、专题页和 XML 文档出现冲突时,以源码和测试所反映的当前实现为准。

View File

@ -1,15 +1,29 @@
---
title: CQRS
description: 当前推荐的新请求模型,统一覆盖 command、query、notification、stream request 和 pipeline behaviors
description: Cqrs 模块族的运行时、契约层、生成器入口,以及 XML / API 阅读链路
---
# CQRS
`GFramework.Cqrs` 是当前推荐的新请求模型 runtime。
`Cqrs` 栏目对应三个直接相关的消费模块:
如果你在写新功能,优先使用这套模型,而不是继续扩展 `GFramework.Core.Command` / `Query` 的兼容层。
- `GFramework.Cqrs`
- `GFramework.Cqrs.Abstractions`
- `GFramework.Cqrs.SourceGenerators`
## 安装方式
如果你在写新功能,优先使用这套请求模型,而不是继续扩展 `GFramework.Core.Command` / `Query` 的兼容层。
## 模块族边界
| 模块 | 角色 | 何时安装 |
| --- | --- | --- |
| `GeWuYou.GFramework.Cqrs.Abstractions` | 纯契约层,定义 request、notification、stream、handler、pipeline、runtime seam | 需要把消息契约放到更稳定的共享层,或只依赖接口做解耦 |
| `GeWuYou.GFramework.Cqrs` | 默认 runtime提供 dispatcher、handler 基类、上下文扩展和程序集注册流程 | 大多数直接消费 CQRS 的业务模块 |
| `GeWuYou.GFramework.Cqrs.SourceGenerators` | 编译期生成 `ICqrsHandlerRegistry`,缩小运行时反射扫描范围 | handler 较多,想把注册映射前移到编译期 |
## 最小接入路径
最小安装组合是:
```bash
dotnet add package GeWuYou.GFramework.Cqrs
@ -22,15 +36,6 @@ dotnet add package GeWuYou.GFramework.Cqrs.Abstractions
dotnet add package GeWuYou.GFramework.Cqrs.SourceGenerators
```
## 先理解分层
- `GFramework.Cqrs.Abstractions`
- 纯契约层,定义请求、处理器、行为等接口
- `GFramework.Cqrs`
- 默认 runtime、dispatcher、处理器基类和上下文扩展
- `GFramework.Cqrs.SourceGenerators`
- 可选生成器,为消费端程序集生成 `ICqrsHandlerRegistry`
## 最小示例
消息基类和处理器基类在不同命名空间:
@ -38,12 +43,10 @@ dotnet add package GeWuYou.GFramework.Cqrs.SourceGenerators
- 消息基类:`GFramework.Cqrs.Command` / `Query` / `Notification`
- 处理器基类:`GFramework.Cqrs.Cqrs.Command` / `Query` / `Notification`
示例:
```csharp
using GFramework.Cqrs.Abstractions.Cqrs.Command;
using GFramework.Cqrs.Command;
using GFramework.Cqrs.Cqrs.Command;
using GFramework.Cqrs.Abstractions.Cqrs.Command;
public sealed record CreatePlayerInput(string Name) : ICommandInput;
@ -66,9 +69,7 @@ public sealed class CreatePlayerCommandHandler
}
```
## 发送请求
如果你在 `IContextAware` 对象内部:
如果你在 `IContextAware` 对象内部发送请求:
```csharp
using GFramework.Cqrs.Extensions;
@ -77,7 +78,7 @@ var playerId = await this.SendAsync(
new CreatePlayerCommand(new CreatePlayerInput("Alice")));
```
如果你在组合根或测试里:
如果你在组合根或测试里发送请求
```csharp
var playerId = await architecture.Context.SendRequestAsync(
@ -92,7 +93,7 @@ var playerId = await architecture.Context.SendRequestAsync(
- `PublishAsync(...)`
- `CreateStream(...)`
## 查询、通知和流
## 统一请求模型
这套 runtime 不只处理 command也统一处理
@ -103,9 +104,9 @@ var playerId = await architecture.Context.SendRequestAsync(
- Stream Request
- 返回 `IAsyncEnumerable<T>`
也就是说,新代码通常不需要再分别设计“命令总线”“查询总线”和另一套通知分发语义。
新代码通常不需要再分别设计“命令总线”“查询总线”和另一套通知分发语义。
## 注册处理器
## 处理器注册与生成器协作
在标准 `Architecture` 启动路径中CQRS runtime 会自动接入基础设施。你通常只需要在 `OnInitialize()` 里追加行为或额外程序集:
@ -123,11 +124,15 @@ protected override void OnInitialize()
}
```
默认逻辑会
默认注册流程当前遵循这些语义
1. 优先使用消费端程序集上的生成注册器
2. 生成注册器不可用时回退到反射扫描
3. 对同一程序集去重,避免重复注册
1. 优先读取消费端程序集上的 `CqrsHandlerRegistryAttribute`
2. 存在生成注册器时优先使用 `ICqrsHandlerRegistry`
3. 生成注册器不可用或元数据异常时记录告警并回退到反射路径
4. 如果程序集带有 `CqrsReflectionFallbackAttribute`,只补扫剩余 handler
5. 同一程序集按稳定键去重,避免重复注册
`Cqrs.SourceGenerators` 的专题入口见 [../source-generators/cqrs-handler-registry-generator.md](../source-generators/cqrs-handler-registry-generator.md)。
## Pipeline Behavior
@ -145,7 +150,7 @@ RegisterCqrsPipelineBehavior<LoggingBehavior<,>>();
- 审计
- 重试或统一异常封装
旧的 `Mediator` 兼容别名入口已经移除;当前公开入口只有 `RegisterCqrsPipelineBehavior<TBehavior>()`
当前公开入口只有 `RegisterCqrsPipelineBehavior<TBehavior>()`
## 和旧 Command / Query 的关系
@ -157,15 +162,28 @@ RegisterCqrsPipelineBehavior<LoggingBehavior<,>>();
- 新路径
- `GFramework.Cqrs`
`IArchitectureContext` 仍然兼容旧入口,但新代码应优先使用 CQRS runtime。
`IArchitectureContext` 仍然兼容旧入口,但新代码应优先使用 CQRS runtime。
一个简单判断规则:
- 在维护历史代码:允许继续使用旧 Command / Query
- 在写新功能或新模块:优先使用 CQRS
## XML 覆盖基线
下面这份 inventory 记录的是 `2026-04-22``Cqrs` 家族做的一轮轻量 XML 盘点结果:只统计当前运行时、契约层和生成器入口中的类型声明级 XML 覆盖,用来校对 README、landing page 与 API 入口,不把它表述成成员级契约全审计。
| 类型族 | 基线状态 | 代表类型 | 阅读重点 |
| --- | --- | --- | --- |
| `GFramework.Cqrs.Abstractions/Cqrs/` | `20/20` 个类型声明已带 XML 注释 | `ICqrsRuntime``ICqrsHandlerRegistrar``IPipelineBehavior<,>``IRequestHandler<,>``Unit` | 先看请求、处理器和 runtime seam 的最小契约 |
| `GFramework.Cqrs/Command` `Query` `Notification` `Request` `Extensions` | `7/7` 个类型声明已带 XML 注释 | `CommandBase<TInput, TResponse>``QueryBase<TInput, TResponse>``NotificationBase<TInput>``ContextAwareCqrsExtensions` | 看业务侧常用基类和上下文发送入口 |
| `GFramework.Cqrs/Cqrs/` | `12/12` 个类型声明已带 XML 注释 | `AbstractCommandHandler<,>``AbstractQueryHandler<,>``AbstractNotificationHandler<>``LoggingBehavior<,>` | 看默认处理器基类、上下文注入与行为管道 |
| `GFramework.Cqrs` 根入口与 `Internal/` | `19/19` 个类型声明已带 XML 注释 | `CqrsRuntimeFactory``ICqrsHandlerRegistry``CqrsHandlerRegistryAttribute``CqrsReflectionFallbackAttribute``DefaultCqrsRegistrationService` | 看 runtime 创建入口、registry 协议、fallback 语义和程序集去重规则 |
| `GFramework.Cqrs.SourceGenerators/Cqrs/` | `3/3` 个类型声明已带 XML 注释 | `CqrsHandlerRegistryGenerator``RuntimeTypeReferenceSpec``OrderedRegistrationKind` | 看生成注册器、精确 type lookup 和 fallback 诊断边界 |
## 继续阅读
- 架构入口:[architecture](./architecture.md)
- 上下文入口:[context](./context.md)
- 生成器专题:[../source-generators/cqrs-handler-registry-generator.md](../source-generators/cqrs-handler-registry-generator.md)
- 模块 README`GFramework.Cqrs/README.md`

View File

@ -1,3 +1,8 @@
---
title: Core
description: GFramework.Core 与 GFramework.Core.Abstractions 的运行时入口、采用顺序和 XML 阅读导航。
---
# Core
`Core` 栏目对应 `GFramework` 的基础运行时层,主要覆盖 `GFramework.Core``GFramework.Core.Abstractions`,以及与之直接相邻的旧版
@ -29,28 +34,70 @@ dotnet add package GeWuYou.GFramework.Core.Abstractions
`Core` 栏目不是旧版“完整框架教程”的镜像,而是当前实现的入口导航。这里的页面按能力域组织:
- 架构与上下文
- 架构与生命周期
- [architecture](./architecture.md)
- [context](./context.md)
- [lifecycle](./lifecycle.md)
- [async-initialization](./async-initialization.md)
- 组件角色与运行时接入
- [model](./model.md)
- [system](./system.md)
- [utility](./utility.md)
- [environment](./environment.md)
- [extensions](./extensions.md)
- 旧版命令 / 查询执行器与迁移入口
- [command](./command.md)
- [query](./query.md)
- [cqrs](./cqrs.md)
- 核心横切能力
- 状态、事件与规则
- [events](./events.md)
- [property](./property.md)
- [rule](./rule.md)
- [logging](./logging.md)
- [resource](./resource.md)
- [coroutine](./coroutine.md)
- [ioc](./ioc.md)
- 状态与扩展能力
- [state-machine](./state-machine.md)
- [state-management](./state-management.md)
- 运行时支撑能力
- [resource](./resource.md)
- [pool](./pool.md)
- [coroutine](./coroutine.md)
- [pause](./pause.md)
- [localization](./localization.md)
- [configuration](./configuration.md)
- [ioc](./ioc.md)
- 通用辅助能力
- [functional](./functional.md)
- [extensions](./extensions.md)
## XML 与 API 阅读入口
如果你已经知道模块归属,但想确认公开类型的契约边界,建议按下面顺序阅读:
1. 先看模块 README `GFramework.Core/README.md`,确认包关系和目录边界
2. 再看本栏目对应专题页,确认采用顺序、生命周期与推荐接线方式
3. 最后回到源码中的 XML 文档,重点核对这些类型族:
- `Architecture` / `IArchitectureContext`
- `CommandExecutor` / `QueryExecutor`
- `ILogger` / `ILoggerFactory`
- `IResourceManager` / `IConfigurationManager`
- `IAsyncKeyLockManager` / `ITimeProvider`
统一入口见 [`../api-reference/index.md`](../api-reference/index.md)。
## XML 覆盖基线
下面这份 inventory 记录的是 `2026-04-22``GFramework.Core` 做的一轮轻量 XML 盘点结果:只统计顶层目录中的公开 /
内部类型声明是否带 XML 注释,用来确认阅读入口和治理优先级;成员级 ``<param>``、``<returns>``、异常语义与线程说明仍需要继续细审。
| 类型族 | 基线状态 | 代表类型 | 阅读重点 |
| --- | --- | --- | --- |
| `Architectures/` | `16/16` 个类型声明已带 XML 注释 | `Architecture``ArchitectureContext``ArchitectureLifecycle``ArchitecturePhaseCoordinator` | 看架构启动、模块安装、阶段切换和上下文暴露边界 |
| `Services/` | `6/6` 个类型声明已带 XML 注释 | `ServiceModuleManager``CommandExecutorModule``CqrsRuntimeModule` | 看服务模块的注册顺序、销毁语义和默认接线 |
| `Command/` `Query/` | `15/15` 个类型声明已带 XML 注释 | `CommandExecutor``AsyncQueryExecutor``AbstractCommand<TInput>``AbstractQuery<TResult>` | 看旧入口兼容面与向 `CQRS` 迁移时还保留了哪些执行契约 |
| `Events/` `Property/` | `19/19` 个类型声明已带 XML 注释 | `EventBus``EnhancedEventBus``BindableProperty<T>``OrEvent<T>` | 看事件传播、解绑约束和可绑定属性的订阅语义 |
| `State/` `StateManagement/` | `10/10` 个类型声明已带 XML 注释 | `StateMachine``StateMachineSystem``Store<TState>``StoreBuilder<TState>` | 看状态切换、selector / middleware / dispatch 的单向流边界 |
| `Coroutine/` `Time/` `Pause/` `Concurrency/` | `43/43` 个类型声明已带 XML 注释 | `CoroutineScheduler``CoroutineHandle``WaitForSecondsRealtime``PauseStackManager``AsyncKeyLockManager` | 看调度阶段、等待指令、时间源和暂停 / 锁的线程语义 |
| `Resource/` `Pool/` | `8/8` 个类型声明已带 XML 注释 | `ResourceManager``AutoReleaseStrategy``ManualReleaseStrategy``AbstractObjectPoolSystem<TKey, TObject>` | 看资源句柄释放策略与对象池复用约束 |
| `Logging/` `Localization/` `Configuration/` `Environment/` `Ioc/` | `31/31` 个类型声明已带 XML 注释 | `ConsoleLogger``CompositeLogger``LocalizationManager``ConfigurationManager``MicrosoftDiContainer` | 看日志组装、格式化 / filter、配置监听、环境对象与容器适配 |
| `Model/` `Systems/` `Utility/` `Rule/` `Extensions/` `Functional/` | `34/34` 个类型声明已带 XML 注释 | `AbstractModel``AbstractSystem``NumericDisplayFormatter``ContextAwareBase``Result<T>` | 看默认基类、上下文感知 helper、数值格式化和通用扩展的使用边界 |
## 最小接入路径
@ -104,4 +151,5 @@ public sealed class CounterArchitecture : Architecture
- `GFramework.Core/README.md`
- `GFramework.Core.Abstractions/README.md`
- `docs/zh-CN/api-reference/index.md`
- 仓库根 `README.md`

View File

@ -1,46 +1,43 @@
---
title: Arch ECS 集成
description: GFramework 的 Arch ECS 集成包使用指南,提供高性能的实体组件系统支持
description: GFramework.Ecs.Arch 的默认运行时装配路径、系统桥接方式与 XML 阅读入口
---
# Arch ECS 集成
## 概述
`GFramework.Ecs.Arch` 是当前仓库里负责 Arch ECS 默认接入路径的运行时包。它把 Arch `World`、GFramework 的
`IServiceModule` 生命周期,以及 `AbstractSystem` / `ISystem` 体系桥接到同一条初始化与更新链路中。
`GFramework.Ecs.Arch` 是 GFramework 的 Arch ECS 集成包,提供开箱即用的 ECSEntity Component
System支持。基于 [Arch.Core](https://github.com/genaray/Arch) 实现,具有极致的性能和简洁的 API。
## 什么时候依赖它
**主要特性**
当你需要下面任一能力时,应直接依赖 `GeWuYou.GFramework.Ecs.Arch`
- 🎯 **显式集成** - 符合 .NET 生态习惯的显式注册方式
- 🔌 **零依赖** - 不使用时Core 包无 Arch 依赖
- 🎯 **类型安全** - 完整的类型系统和编译时检查
- ⚡ **高性能** - 基于 Arch ECS 的高性能实现
- 🔧 **易扩展** - 简单的系统适配器模式
- 📊 **优先级支持** - 系统按优先级顺序执行
- 在架构实例上调用 `UseArch(...)`
- 让 `World` 在服务模块注册阶段自动创建并注入容器
- 让 ECS 系统继承 `ArchSystemAdapter<T>`
- 使用仓库自带的 `Position``Velocity``MovementSystem` 最小示例
**性能特点**
如果你只想保留共享边界,而不依赖默认实现,请改看
[`../abstractions/ecs-arch-abstractions.md`](../abstractions/ecs-arch-abstractions.md)。
- 10,000 个实体更新 < 100ms
- 1,000 个实体创建 < 50ms
- 基于 Archetype 的高效内存布局
- 零 GC 分配的组件访问
## 最小接入路径
## 安装
### 1. 安装包
```bash
dotnet add package GeWuYou.GFramework.Ecs.Arch
```
## 快速开始
### 2. 在 `Initialize()` 之前调用 `UseArch(...)`
### 1. 注册 ECS 模块
当前实现通过 `ArchitectureModuleRegistry.Register(...)` 提前登记 `ArchEcsModule`。这意味着调用时机应位于
`Initialize()` 之前,而不是放进 `OnInitialize()` 里。
```csharp
using GFramework.Core.Architecture;
using GFramework.Core.Architectures;
using GFramework.Ecs.Arch.Extensions;
public class GameArchitecture : Architecture
public sealed class GameArchitecture : Architecture
{
public GameArchitecture() : base(new ArchitectureConfiguration())
{
@ -48,698 +45,100 @@ public class GameArchitecture : Architecture
protected override void OnInitialize()
{
// 显式注册 Arch ECS 模块
this.UseArch();
RegisterSystem<MovementSystem>();
}
}
// 初始化架构
var architecture = new GameArchitecture();
var architecture = new GameArchitecture()
.UseArch(options =>
{
options.WorldCapacity = 2048;
options.Priority = 50;
});
architecture.Initialize();
```
### 2. 带配置的注册
### 3. 用 `ArchSystemAdapter<float>` 编写系统
```csharp
public class GameArchitecture : Architecture
{
protected override void OnInitialize()
{
// 带配置的注册
this.UseArch(options =>
{
options.WorldCapacity = 2000; // World 初始容量
options.EnableStatistics = true; // 启用统计信息
options.Priority = 50; // 模块优先级
});
}
}
```
### 3. 定义组件
组件是纯数据结构,使用 `struct` 定义:
```csharp
using System.Runtime.InteropServices;
namespace MyGame.Components;
[StructLayout(LayoutKind.Sequential)]
public struct Position(float x, float y)
{
public float X { get; set; } = x;
public float Y { get; set; } = y;
}
[StructLayout(LayoutKind.Sequential)]
public struct Velocity(float x, float y)
{
public float X { get; set; } = x;
public float Y { get; set; } = y;
}
[StructLayout(LayoutKind.Sequential)]
public struct Health(float current, float max)
{
public float Current { get; set; } = current;
public float Max { get; set; } = max;
}
```
### 4. 创建系统
系统继承自 `ArchSystemAdapter&lt;T&gt;`
`ArchSystemAdapter<T>``OnInit()` 中从当前上下文解析 `World`,再把 Arch 的 `Initialize / BeforeUpdate /
AfterUpdate / Dispose` 钩子桥接到可重写方法。
```csharp
using Arch.Core;
using GFramework.Ecs.Arch;
using MyGame.Components;
using GFramework.Ecs.Arch.Components;
namespace MyGame.Systems;
/// <summary>
/// 移动系统 - 更新实体位置
/// </summary>
public sealed class MovementSystem : ArchSystemAdapter<float>
{
private QueryDescription _query;
protected override void OnArchInitialize()
{
// 创建查询:查找所有同时拥有 Position 和 Velocity 组件的实体
_query = new QueryDescription()
.WithAll<Position, Velocity>();
}
protected override void OnUpdate(in float deltaTime)
{
// 查询并更新所有符合条件的实体
World.Query(in _query, (ref Position pos, ref Velocity vel) =>
var frameDelta = deltaTime;
World.Query(in _query, (ref Position position, ref Velocity velocity) =>
{
pos.X += vel.X * deltaTime;
pos.Y += vel.Y * deltaTime;
position.X += velocity.X * frameDelta;
position.Y += velocity.Y * frameDelta;
});
}
}
```
### 5. 注册系统
```csharp
public class GameArchitecture : Architecture
{
protected override void OnInitialize()
{
this.UseArch();
// 注册 ECS 系统
RegisterSystem<MovementSystem>();
}
}
```
### 6. 创建实体
### 4. 初始化后解析 `World` 与模块服务
```csharp
using Arch.Core;
using GFramework.Core.Abstractions.Rule;
using GFramework.Core.SourceGenerators.Abstractions.Rule;
using MyGame.Components;
[ContextAware]
public partial class GameController
{
public void Start()
{
// 获取 World
var world = this.GetService<World>();
// 创建实体
var player = world.Create(
new Position(0, 0),
new Velocity(0, 0),
new Health(100, 100)
);
var enemy = world.Create(
new Position(10, 10),
new Velocity(-1, 0),
new Health(50, 50)
);
}
}
```
### 7. 更新系统
```csharp
using GFramework.Ecs.Arch.Abstractions;
public class GameLoop
{
private IArchEcsModule _ecsModule;
public void Initialize()
{
// 获取 ECS 模块
_ecsModule = architecture.Context.GetService<IArchEcsModule>();
}
public void Update(float deltaTime)
{
// 更新所有 ECS 系统
_ecsModule.Update(deltaTime);
}
}
var world = architecture.Context.GetService<World>();
var ecsModule = architecture.Context.GetService<IArchEcsModule>();
```
## 配置选项
### ArchOptions
### 5. 由宿主循环显式调用 `Update`
```csharp
public sealed class ArchOptions
{
/// <summary>
/// World 初始容量默认1000
/// </summary>
public int WorldCapacity { get; set; } = 1000;
/// <summary>
/// 是否启用统计信息默认false
/// </summary>
public bool EnableStatistics { get; set; } = false;
/// <summary>
/// 模块优先级默认50
/// </summary>
public int Priority { get; set; } = 50;
}
ecsModule.Update(deltaTime);
```
### 配置示例
这一步在 `GFramework.Ecs.Arch.Tests/Ecs/*.cs` 中也采用同样的驱动方式。
```csharp
this.UseArch(options =>
{
// 设置 World 初始容量
// 根据预期实体数量设置,避免频繁扩容
options.WorldCapacity = 2000;
## 运行时职责
// 启用统计信息(开发/调试时使用)
options.EnableStatistics = true;
| 类型 | 责任 | 证据文件 |
| --- | --- | --- |
| `ArchExtensions` | 把 `ArchEcsModule` 注册到 `ArchitectureModuleRegistry` | `GFramework.Ecs.Arch/Extensions/ArchExtensions.cs` |
| `ArchEcsModule` | 创建并注册 `World`,按优先级收集 `ArchSystemAdapter<float>`,负责初始化、销毁和逐帧更新 | `GFramework.Ecs.Arch/ArchEcsModule.cs` |
| `ArchSystemAdapter<T>` | 从 GFramework 系统生命周期桥接到 Arch `ISystem<T>` 生命周期 | `GFramework.Ecs.Arch/ArchSystemAdapter.cs` |
| `ArchOptions` | 暴露 `WorldCapacity``EnableStatistics``Priority` 这组运行时配置对象 | `GFramework.Ecs.Arch/ArchOptions.cs` |
// 设置模块优先级
// 数值越小,优先级越高
options.Priority = 50;
});
```
## 配置对象阅读提示
## 核心概念
当前公开配置对象是 `GFramework.Ecs.Arch.ArchOptions`。从源码可直接确认:
### Entity实体
- `WorldCapacity` 用于 `World.Create(...)` 的容量参数
- `Priority` 影响 `ArchEcsModule` 作为服务模块的排序
- `EnableStatistics` 目前保留在公开配置面上;采用时应以源码 XML 注释和实现行为为准,而不是依赖旧文档推断
实体是游戏世界中的基本对象,本质上是一个唯一标识符:
## 类型族级 XML Inventory
```csharp
// 创建空实体
var entity = world.Create();
| 类型族 | 代表类型 | XML 状态 | 阅读重点 |
| --- | --- | --- | --- |
| 装配入口 | `ArchExtensions` | 已覆盖 | `UseArch(...)` 的时机、链式调用返回值 |
| 服务模块 | `ArchEcsModule` | 已覆盖 | `World` 注册、系统收集、模块销毁顺序 |
| 系统桥接层 | `ArchSystemAdapter<T>` | 已覆盖 | `OnArchInitialize` / `OnUpdate` / `OnArchDispose` |
| 示例类型 | `Position``Velocity``MovementSystem` | 已覆盖 | 组件布局、查询写法、最小集成样例 |
// 创建带组件的实体
var entity = world.Create(
new Position(0, 0),
new Velocity(1, 1)
);
## 相关入口
// 销毁实体
world.Destroy(entity);
```
### Component组件
组件是纯数据结构,用于存储实体的状态:
```csharp
// 添加组件
world.Add(entity, new Position(0, 0));
// 检查组件
if (world.Has<Position>(entity))
{
// 获取组件引用(零 GC 分配)
ref var pos = ref world.Get<Position>(entity);
pos.X += 10;
}
// 设置组件(替换现有值)
world.Set(entity, new Position(100, 100));
// 移除组件
world.Remove<Velocity>(entity);
```
### System系统
系统包含游戏逻辑,处理具有特定组件组合的实体:
```csharp
public sealed class DamageSystem : ArchSystemAdapter<float>
{
private QueryDescription _query;
protected override void OnArchInitialize()
{
// 初始化查询
_query = new QueryDescription()
.WithAll<Health, Damage>();
}
protected override void OnUpdate(in float deltaTime)
{
// 处理伤害
World.Query(in _query, (Entity entity, ref Health health, ref Damage damage) =>
{
health.Current -= damage.Value * deltaTime;
if (health.Current <= 0)
{
health.Current = 0;
World.Remove<Damage>(entity);
}
});
}
}
```
### World世界
World 是 ECS 的核心容器,管理所有实体和组件:
```csharp
// World 由 ArchEcsModule 自动创建和注册
var world = this.GetService<World>();
// 获取实体数量
var entityCount = world.Size;
// 清空所有实体
world.Clear();
```
## 系统适配器
### ArchSystemAdapter&lt;T&gt;
`ArchSystemAdapter&lt;T&gt;` 桥接 Arch.System.ISystem&lt;T&gt; 到 GFramework 架构:
```csharp
public sealed class MySystem : ArchSystemAdapter<float>
{
// Arch 系统初始化
protected override void OnArchInitialize()
{
// 创建查询、初始化资源
}
// 更新前调用
protected override void OnBeforeUpdate(in float deltaTime)
{
// 预处理逻辑
}
// 主更新逻辑
protected override void OnUpdate(in float deltaTime)
{
// 处理实体
}
// 更新后调用
protected override void OnAfterUpdate(in float deltaTime)
{
// 后处理逻辑
}
// 资源清理
protected override void OnArchDispose()
{
// 清理资源
}
}
```
### 访问 World
在系统中可以直接访问 `World` 属性:
```csharp
public sealed class MySystem : ArchSystemAdapter<float>
{
protected override void OnUpdate(in float deltaTime)
{
// 访问 World
var entityCount = World.Size;
// 创建实体
var entity = World.Create(new Position(0, 0));
// 查询实体
var query = new QueryDescription().WithAll<Position>();
World.Query(in query, (ref Position pos) =>
{
// 处理逻辑
});
}
}
```
### 访问框架服务
`ArchSystemAdapter&lt;T&gt;` 继承自 `AbstractSystem`,可以使用所有 GFramework 的扩展方法:
```csharp
public sealed class ServiceAccessSystem : ArchSystemAdapter<float>
{
protected override void OnUpdate(in float deltaTime)
{
// 获取 Model
var playerModel = this.GetModel<PlayerModel>();
// 获取 Utility
var timeUtility = this.GetUtility<TimeUtility>();
// 发送命令
this.SendCommand(new SaveGameCommand());
// 发送查询
var score = this.SendQuery(new GetScoreQuery());
// 发送事件
this.SendEvent(new GameOverEvent());
}
}
```
## 查询实体
### 基本查询
```csharp
// 查询:必须有 Position 和 Velocity
var query = new QueryDescription()
.WithAll<Position, Velocity>();
World.Query(in query, (ref Position pos, ref Velocity vel) =>
{
pos.X += vel.X * deltaTime;
pos.Y += vel.Y * deltaTime;
});
```
### 过滤查询
```csharp
// 查询:必须有 Health但不能有 Damage
var query = new QueryDescription()
.WithAll<Health>()
.WithNone<Damage>();
World.Query(in query, (ref Health health) =>
{
// 只处理没有受伤的实体
});
```
### 可选组件查询
```csharp
// 查询:必须有 Position可选 Velocity
var query = new QueryDescription()
.WithAll<Position>()
.WithAny<Velocity>();
World.Query(in query, (Entity entity, ref Position pos) =>
{
// 处理逻辑
});
```
### 访问实体 ID
```csharp
var query = new QueryDescription().WithAll<Position>();
World.Query(in query, (Entity entity, ref Position pos) =>
{
// 可以访问实体 ID
Console.WriteLine($"Entity {entity.Id}: ({pos.X}, {pos.Y})");
// 可以对实体进行操作
if (pos.X > 100)
{
World.Destroy(entity);
}
});
```
## 系统优先级
系统按照优先级顺序执行,数值越小优先级越高:
```csharp
using GFramework.Core.Abstractions.bases;
using GFramework.Core.SourceGenerators.Abstractions.Bases;
// 使用 Priority 特性设置优先级
[Priority(10)] // 高优先级,先执行
public sealed class InputSystem : ArchSystemAdapter<float>
{
// ...
}
[Priority(20)] // 中优先级
public sealed class MovementSystem : ArchSystemAdapter<float>
{
// ...
}
[Priority(30)] // 低优先级,后执行
public sealed class RenderSystem : ArchSystemAdapter<float>
{
// ...
}
```
执行顺序InputSystem → MovementSystem → RenderSystem
## 性能优化
### 1. 使用 struct 组件
```csharp
// ✅ 推荐:使用 struct
[StructLayout(LayoutKind.Sequential)]
public struct Position(float x, float y)
{
public float X { get; set; } = x;
public float Y { get; set; } = y;
}
// ❌ 不推荐:使用 class
public class Position
{
public float X { get; set; }
public float Y { get; set; }
}
```
### 2. 缓存查询
```csharp
public class OptimizedSystem : ArchSystemAdapter<float>
{
// ✅ 推荐:缓存查询
private QueryDescription _cachedQuery;
protected override void OnArchInitialize()
{
_cachedQuery = new QueryDescription()
.WithAll<Position, Velocity>();
}
protected override void OnUpdate(in float deltaTime)
{
World.Query(in _cachedQuery, (ref Position pos, ref Velocity vel) =>
{
pos.X += vel.X * deltaTime;
pos.Y += vel.Y * deltaTime;
});
}
}
```
### 3. 使用 ref 访问组件
```csharp
// ✅ 推荐:使用 ref 避免复制
World.Query(in query, (ref Position pos, ref Velocity vel) =>
{
pos.X += vel.X; // 直接修改,零 GC
});
// ❌ 不推荐:不使用 ref
World.Query(in query, (Position pos, Velocity vel) =>
{
pos.X += vel.X; // 复制值,修改不会生效
});
```
### 4. 组件大小优化
```csharp
// ✅ 推荐:小而专注的组件
public struct Position(float x, float y)
{
public float X { get; set; } = x;
public float Y { get; set; } = y;
}
public struct Velocity(float x, float y)
{
public float X { get; set; } = x;
public float Y { get; set; } = y;
}
// ❌ 不推荐:大而全的组件
public struct Transform
{
public float X, Y, Z;
public float RotationX, RotationY, RotationZ;
public float ScaleX, ScaleY, ScaleZ;
public float VelocityX, VelocityY, VelocityZ;
// ... 太多数据
}
```
## 最佳实践
### 1. 组件设计原则
- 使用 `struct` 而不是 `class`
- 只包含数据,不包含逻辑
- 使用 `[StructLayout(LayoutKind.Sequential)]` 优化内存布局
- 保持组件小而专注
### 2. 系统设计原则
- 单一职责:每个系统只负责一件事
- 缓存查询:在 `OnArchInitialize` 中创建查询
- 使用 ref访问组件时使用 ref 参数
- 批量处理:一次查询处理所有实体
### 3. 标签组件
使用空结构体作为标签来分类实体:
```csharp
// 定义标签组件
public struct PlayerTag { }
public struct EnemyTag { }
public struct DeadTag { }
// 使用标签过滤实体
var query = new QueryDescription()
.WithAll<Position, Velocity, PlayerTag>()
.WithNone<DeadTag>();
```
### 4. 与传统架构结合
```csharp
// ECS 系统可以访问 Model
public class EnemySpawnSystem : ArchSystemAdapter<float>
{
protected override void OnUpdate(in float deltaTime)
{
var gameState = this.GetModel<GameStateModel>();
// 根据关卡生成敌人
for (int i = 0; i < gameState.Level; i++)
{
World.Create(
new Position(Random.Shared.Next(0, 100), 0),
new Velocity(0, -1),
new Health(50, 50)
);
}
}
}
```
## 常见问题
### Q: 如何在运行时动态添加/移除组件?
A: Arch 支持运行时修改实体的组件:
```csharp
// 动态添加组件
if (pos.X > 100 && !World.Has<FastTag>(entity))
{
World.Add(entity, new FastTag());
}
// 动态移除组件
if (pos.X < 0 && World.Has<FastTag>(entity))
{
World.Remove<FastTag>(entity);
}
```
### Q: 如何处理实体之间的交互?
A: 使用嵌套查询或事件:
```csharp
// 方式 1嵌套查询
World.Query(in playerQuery, (Entity player, ref Position playerPos) =>
{
World.Query(in enemyQuery, (Entity enemy, ref Position enemyPos) =>
{
// 检测碰撞
});
});
// 方式 2使用事件
this.SendEvent(new CollisionEvent
{
Entity1 = player,
Entity2 = enemy
});
```
### Q: 如何调试 ECS 系统?
A: 使用日志和统计信息:
```csharp
protected override void OnUpdate(in float deltaTime)
{
// 打印实体数量
Console.WriteLine($"Total entities: {World.Size}");
// 查询特定实体
var query = new QueryDescription().WithAll<Position>();
var count = 0;
World.Query(in query, (Entity entity, ref Position pos) =>
{
count++;
Console.WriteLine($"Entity {entity.Id}: ({pos.X}, {pos.Y})");
});
}
```
## 相关资源
- [Arch.Core 官方文档](https://github.com/genaray/Arch)
- [ECS 概述](./index.md)
- ECS 模块总览:[`index.md`](./index.md)
- 抽象契约页:[`../abstractions/ecs-arch-abstractions.md`](../abstractions/ecs-arch-abstractions.md)
- 仓库模块 README`GFramework.Ecs.Arch/README.md`
- 统一 API / XML 导航:[`../api-reference/index.md`](../api-reference/index.md)

View File

@ -1,95 +1,39 @@
---
title: ECS 系统集成
description: GFramework 的 ECSEntity Component System集成方案支持多种 ECS 框架
description: GFramework 当前 ECS 模块族的包边界、采用顺序与 XML 阅读入口
---
# ECS 系统集成
## 概述
GFramework 当前仓库内已经交付并持续维护的 ECS 模块族是 `Ecs.Arch`。它分成运行时实现包
`GFramework.Ecs.Arch` 和契约包 `GFramework.Ecs.Arch.Abstractions`,分别覆盖默认装配能力与共享边界约定。
GFramework 提供了灵活的 ECSEntity Component System集成方案允许你根据项目需求选择合适的 ECS 框架。ECS
是一种数据驱动的架构模式,特别适合处理大量相似实体的场景。
## 当前模块族
## 什么是 ECS
| 包 | 适用场景 | 你会得到什么 | 继续阅读 |
| --- | --- | --- | --- |
| `GFramework.Ecs.Arch` | 需要默认运行时、`UseArch(...)` 装配入口、`World` 注册和系统适配基类 | `ArchEcsModule``ArchSystemAdapter<T>``ArchExtensions.UseArch(...)`、示例组件与系统 | [`arch.md`](./arch.md) |
| `GFramework.Ecs.Arch.Abstractions` | 只想让共享宿主循环、测试替身或扩展模块依赖最小契约,而不引入默认运行时 | `IArchEcsModule``IArchSystemAdapter<T>``ArchOptions` 契约对象 | [`../abstractions/ecs-arch-abstractions.md`](../abstractions/ecs-arch-abstractions.md) |
ECSEntity Component System是一种架构模式将游戏对象分解为三个核心概念
## 最小采用路径
- **Entity实体**:游戏世界中的基本对象,本质上是一个唯一标识符
- **Component组件**:纯数据结构,存储实体的状态
- **System系统**:包含游戏逻辑,处理具有特定组件组合的实体
### 1. 选择包边界
### ECS 的优势
- 需要默认实现时安装 `GeWuYou.GFramework.Ecs.Arch`
- 只需要契约时安装 `GeWuYou.GFramework.Ecs.Arch.Abstractions`
- **高性能**:数据局部性好,缓存友好
- **可扩展**:通过组合组件轻松创建新实体类型
- **并行处理**:系统之间相互独立,易于并行化
- **数据驱动**:逻辑与数据分离,便于序列化和网络同步
### 2. 在 `Initialize()` 前显式接入运行时
### 何时使用 ECS
**适合使用 ECS 的场景**
- 大量相似实体(敌人、子弹、粒子)
- 需要高性能批量处理
- 复杂的实体组合和变化
- 需要并行处理的系统
**不适合使用 ECS 的场景**
- 全局状态管理
- 单例服务
- UI 逻辑
- 游戏流程控制
## 支持的 ECS 框架
GFramework 采用可选集成的设计,你可以根据需求选择合适的 ECS 框架:
### Arch ECS推荐
[Arch](https://github.com/genaray/Arch) 是一个高性能的 C# ECS 框架,具有以下特点:
- ✅ **极致性能**:基于 Archetype 的内存布局,零 GC 分配
- ✅ **简单易用**:清晰的 API易于上手
- ✅ **功能完整**:支持查询、过滤、并行处理等高级特性
- ✅ **活跃维护**:社区活跃,持续更新
**安装方式**
```bash
dotnet add package GeWuYou.GFramework.Ecs.Arch
```
**文档链接**[Arch ECS 集成指南](./arch.md)
### 其他 ECS 框架
GFramework 的设计允许集成其他 ECS 框架,未来可能支持:
- **DefaultEcs**:轻量级 ECS 框架
- **Entitas**:成熟的 ECS 框架Unity 生态常用
- **自定义 ECS**:你可以基于 GFramework 的模块系统实现自己的 ECS 集成
## 快速开始
### 1. 选择 ECS 框架
根据项目需求选择合适的 ECS 框架。对于大多数项目,我们推荐使用 Arch ECS。
### 2. 安装集成包
```bash
# 安装 Arch ECS 集成包
dotnet add package GeWuYou.GFramework.Ecs.Arch
```
### 3. 注册 ECS 模块
`UseArch(...)` 通过 `ArchitectureModuleRegistry` 注册服务模块。按当前源码与集成测试,它应在架构实例调用
`Initialize()` 之前完成。
```csharp
using GFramework.Core.Architecture;
using GFramework.Ecs.Arc;
using Arch.Core;
using GFramework.Core.Architectures;
using GFramework.Ecs.Arch.Abstractions;
using GFramework.Ecs.Arch.Extensions;
public class GameArchitecture : Architecture
public sealed class GameArchitecture : Architecture
{
public GameArchitecture() : base(new ArchitectureConfiguration())
{
@ -97,41 +41,29 @@ public class GameArchitecture : Architecture
protected override void OnInitialize()
{
// 显式注册 Arch ECS 模块
this.UseArch(options =>
{
options.WorldCapacity = 2000;
options.EnableStatistics = true;
});
RegisterSystem<MovementSystem>();
}
}
var architecture = new GameArchitecture()
.UseArch(options =>
{
options.WorldCapacity = 2048;
options.Priority = 50;
});
architecture.Initialize();
var world = architecture.Context.GetService<World>();
var ecsModule = architecture.Context.GetService<IArchEcsModule>();
```
### 4. 定义组件
```csharp
using System.Runtime.InteropServices;
[StructLayout(LayoutKind.Sequential)]
public struct Position(float x, float y)
{
public float X { get; set; } = x;
public float Y { get; set; } = y;
}
[StructLayout(LayoutKind.Sequential)]
public struct Velocity(float x, float y)
{
public float X { get; set; } = x;
public float Y { get; set; } = y;
}
```
### 5. 创建系统
### 3. 让 ECS 系统继承 `ArchSystemAdapter<float>`
```csharp
using Arch.Core;
using GFramework.Ecs.Arch;
using GFramework.Ecs.Arch.Components;
public sealed class MovementSystem : ArchSystemAdapter<float>
{
@ -145,147 +77,60 @@ public sealed class MovementSystem : ArchSystemAdapter<float>
protected override void OnUpdate(in float deltaTime)
{
World.Query(in _query, (ref Position pos, ref Velocity vel) =>
var frameDelta = deltaTime;
World.Query(in _query, (ref Position position, ref Velocity velocity) =>
{
pos.X += vel.X * deltaTime;
pos.Y += vel.Y * deltaTime;
position.X += velocity.X * frameDelta;
position.Y += velocity.Y * frameDelta;
});
}
}
```
### 6. 注册系统
### 4. 由宿主循环驱动更新
`IArchEcsModule` 继承自 `IServiceModule`,负责初始化和销毁;真正的帧更新通过 `Update(float deltaTime)` 显式触发。
```csharp
public class GameArchitecture : Architecture
{
protected override void OnInitialize()
{
this.UseArch();
using GFramework.Ecs.Arch.Abstractions;
// 注册 ECS 系统
RegisterSystem<MovementSystem>();
public sealed class GameLoop
{
private readonly IArchEcsModule _ecsModule;
public GameLoop(IArchEcsModule ecsModule)
{
_ecsModule = ecsModule;
}
public void Tick(float deltaTime)
{
_ecsModule.Update(deltaTime);
}
}
```
## 设计理念
## 阅读顺序
### 显式集成
1. 先看本页,确认自己要的是运行时包还是契约包
2. 需要默认实现时继续读 [`arch.md`](./arch.md)
3. 只想保留共享边界时继续读 [`../abstractions/ecs-arch-abstractions.md`](../abstractions/ecs-arch-abstractions.md)
4. 统一查阅 README / docs / XML 入口时回到 [`../api-reference/index.md`](../api-reference/index.md)
GFramework 采用显式集成的设计,而不是自动注册:
## 类型族级 XML Inventory
```csharp
// ✅ 显式注册 - 清晰、可控
public class GameArchitecture : Architecture
{
protected override void OnInitialize()
{
this.UseArch(); // 明确表示使用 Arch ECS
}
}
下表记录当前 `Ecs.Arch` family 的类型声明级 XML 基线,便于从 README、站内 landing 和源码之间建立一致的审计入口。
// ❌ 自动注册 - 隐式、难以控制
// 只需引入包,自动注册(不推荐)
```
| 包 | 类型族 | 代表类型 | XML 状态 | 阅读重点 |
| --- | --- | --- | --- | --- |
| `GFramework.Ecs.Arch` | 运行时装配与模块生命周期 | `ArchExtensions``ArchEcsModule` | 已覆盖 | `UseArch(...)` 的接入时机、`World` 注册、模块优先级 |
| `GFramework.Ecs.Arch` | 系统桥接层 | `ArchSystemAdapter<T>` | 已覆盖 | GFramework `ISystem` 生命周期如何桥接到 Arch `ISystem<T>` |
| `GFramework.Ecs.Arch` | 示例组件与系统 | `Position``Velocity``MovementSystem` | 已覆盖 | 查询写法、组件布局、最小可运行示例 |
| `GFramework.Ecs.Arch.Abstractions` | 契约与配置对象 | `IArchEcsModule``IArchSystemAdapter<T>``ArchOptions` | 已覆盖 | 共享宿主循环、测试替身、跨程序集配置边界 |
**优势**
## 边界说明
- 清晰的依赖关系
- 更好的 IDE 支持
- 易于测试和调试
- 符合 .NET 生态习惯
### 零依赖原则
如果你不使用 ECSGFramework.Core 包不会引入任何 ECS 相关的依赖:
```xml
<!-- GFramework.Core.csproj -->
<ItemGroup>
<!-- 无 Arch 依赖 -->
</ItemGroup>
<!-- GFramework.Ecs.Arch.csproj -->
<ItemGroup>
<PackageReference Include="Arch" Version="2.1.0" />
<PackageReference Include="Arch.System" Version="1.1.0" />
</ItemGroup>
```
### 模块化设计
ECS 集成基于 GFramework 的模块系统:
```csharp
// ECS 模块实现 IServiceModule 接口
public sealed class ArchEcsModule : IArchEcsModule
{
public string ModuleName => nameof(ArchEcsModule);
public int Priority => 50;
public bool IsEnabled { get; }
public void Register(IIocContainer container) { }
public void Initialize() { }
public ValueTask DestroyAsync() { }
public void Update(float deltaTime) { }
}
```
## 与传统架构结合
ECS 可以与 GFramework 的传统架构Model、System、Utility无缝结合
```csharp
// Model 存储全局状态
public class GameStateModel : AbstractModel
{
public int Score { get; set; }
public int Level { get; set; }
}
// ECS System 处理实体逻辑
public class EnemySpawnSystem : ArchSystemAdapter<float>
{
protected override void OnUpdate(in float deltaTime)
{
// 访问 Model
var gameState = this.GetModel<GameStateModel>();
// 根据关卡生成敌人
for (int i = 0; i < gameState.Level; i++)
{
World.Create(
new Position(Random.Shared.Next(0, 100), 0),
new Velocity(0, -1),
new Health(50, 50)
);
}
}
}
// 传统 System 处理游戏逻辑
public class ScoreSystem : AbstractSystem
{
protected override void OnInit()
{
this.RegisterEvent<EnemyDestroyedEvent>(OnEnemyDestroyed);
}
private void OnEnemyDestroyed(EnemyDestroyedEvent e)
{
var gameState = this.GetModel<GameStateModel>();
gameState.Score += 100;
}
}
```
## 下一步
- [Arch ECS 集成指南](./arch.md) - 详细的 Arch ECS 使用文档
## 相关资源
- [Architecture 架构系统](../core/architecture.md)
- [System 系统](../core/system.md)
- [事件系统](../core/events.md)
- 当前仓库没有交付其他可直接消费的 ECS 运行时包;旧文档把“未来可能支持的其他 ECS 框架”写成现有能力,会误导采用路径。
- `GFramework.Ecs.Arch.Abstractions` 负责“边界”,`GFramework.Ecs.Arch` 负责“默认实现”。
- 站内页面只维护可构建的 docs 链路;仓库根 README 和模块 README 继续承担包目录入口职责。

View File

@ -1,3 +1,8 @@
---
title: Game
description: GFramework.Game family 的运行时入口、采用顺序与 XML 阅读基线。
---
# Game
`Game` 栏目对应 `GFramework.Game``GFramework.Game.Abstractions` 这层游戏运行时能力。
@ -98,6 +103,16 @@ IStorage storage = new FileStorage("GameData", serializer);
4. [setting](./setting.md)
5. [scene](./scene.md) 或 [ui](./ui.md)
## Game Family XML 覆盖基线
下面这份 inventory 记录的是 `2026-04-23``Game` family 做的一轮轻量 XML 盘点结果:只统计公开 / 内部类型声明是否带 XML 注释,用来建立 README / landing / API 阅读链路;成员级 `param``returns``exception` 与生命周期说明仍需要后续波次继续细化。
| 模块 | 基线状态 | 代表类型 | 阅读重点 |
| --- | --- | --- | --- |
| `GFramework.Game` | `56/56` 个类型声明已带 XML 注释 | `YamlConfigLoader``SettingsModel<TRepository>``SceneRouterBase``UiRouterBase` | 先看运行时默认实现、配置加载、设置编排和路由基类 |
| `GFramework.Game.Abstractions` | `80/80` 个类型声明已带 XML 注释 | `IConfigRegistry``ISaveRepository<TSaveData>``ISettingsSystem``ISceneRouter``IUiRouter` | 再看契约层边界,决定项目哪些程序集只依赖接口 |
| `GFramework.Game.SourceGenerators` | `2/2` 个类型声明已带 XML 注释 | `SchemaConfigGenerator``ConfigSchemaDiagnostics` | 最后看 schema 生成入口与诊断模型,确认配置系统的编译期链路 |
## 与真实接法的关系
这个栏目以源码、`*.csproj`、模块 `README.md``ai-libs/` 下已验证的参考接法为准。

View File

@ -0,0 +1,131 @@
---
title: CQRS Handler Registry 生成器
description: 为消费端程序集生成 CQRS handler registry并在需要时附带精确 reflection fallback 元数据。
---
# CQRS Handler Registry 生成器
`GFramework.Cqrs.SourceGenerators` 会在编译期为当前业务程序集生成 `ICqrsHandlerRegistry`,让 `GFramework.Cqrs`
runtime 在注册 handlers 时优先走静态注册表,而不是先扫描整个程序集。
它服务的是 `Cqrs` 家族,不是独立运行时:
- 契约层:`GeWuYou.GFramework.Cqrs.Abstractions`
- 默认 runtime`GeWuYou.GFramework.Cqrs`
- 编译期生成器:`GeWuYou.GFramework.Cqrs.SourceGenerators`
## 生成什么
当前生成器会分析消费端程序集中的:
- `IRequestHandler<,>`
- `INotificationHandler<>`
- `IStreamRequestHandler<,>`
然后输出两类结果:
1. 一个实现 `ICqrsHandlerRegistry` 的内部注册器类型
2. 程序集级 `CqrsHandlerRegistryAttribute`
当某些 handler 不能被生成代码安全地直接引用时,还会补发:
- 程序集级 `CqrsReflectionFallbackAttribute`
这意味着运行时会先使用生成注册器完成可静态表达的映射,再只对剩余类型做补扫,而不是退回整程序集盲扫。
## 最小接入路径
安装方式保持 runtime 包与生成器包版本一致,并把生成器作为编译期依赖引入:
```xml
<ItemGroup>
<PackageReference Include="GeWuYou.GFramework.Cqrs" Version="x.y.z" />
<PackageReference Include="GeWuYou.GFramework.Cqrs.Abstractions" Version="x.y.z" />
<PackageReference Include="GeWuYou.GFramework.Cqrs.SourceGenerators"
Version="x.y.z"
PrivateAssets="all"
ExcludeAssets="runtime" />
</ItemGroup>
```
运行时侧仍然按 `Core` 的标准入口注册程序集:
```csharp
protected override void OnInitialize()
{
RegisterCqrsHandlersFromAssembly(typeof(GameArchitecture).Assembly);
}
```
如果你的 handlers 分布在多个业务程序集里,则改用:
```csharp
RegisterCqrsHandlersFromAssemblies(
[
typeof(InventoryCqrsMarker).Assembly,
typeof(BattleCqrsMarker).Assembly
]);
```
文档示例统一用 marker 类型承载程序集引用。框架本身不要求固定目录或固定命名,但团队实践里可以把这类空 marker
集中放在每个业务程序集自己的 `Application/Markers` 或等价目录,并采用 `InventoryCqrsMarker` 这类能直接看出来源
的名字,避免多人协作时拿无关业务类型充当程序集定位锚点。
## 运行时如何消费生成结果
`Cqrs` runtime 当前的注册顺序是:
1. 先读取程序集上的 `CqrsHandlerRegistryAttribute`
2. 优先激活生成的 `ICqrsHandlerRegistry`
3. 若生成元数据损坏、registry 不可激活,记录告警并回退到反射路径
4. 若存在 `CqrsReflectionFallbackAttribute`,只补扫剩余 handler
5. 同一程序集按稳定键去重,避免重复注册
这个行为由 `GFramework.Cqrs.Tests/Cqrs/CqrsHandlerRegistrarTests.cs`
`GFramework.SourceGenerators.Tests/Cqrs/CqrsHandlerRegistryGeneratorTests.cs` 共同覆盖。
## 什么时候值得安装
推荐安装:
- 业务程序集内 handler 数量较多
- 想把 handler 注册路径前移到编译期
- 希望冷启动阶段减少整程序集反射扫描
- 需要更明确地观察“哪些 handler 走静态注册,哪些只能走 fallback”
可以先不装:
- 项目体量很小handler 很少
- 当前只做原型,尚不关心注册成本
- 你还没稳定到 `Cqrs` runtime 的最终接入边界
## fallback 边界
生成器并不会承诺“所有 handler 都能被静态表达”。
当前实现遵循一个保守原则:
- 能直接引用的 handler生成直接注册语句
- 实现类型不能直接引用、但服务接口还能精确表达时,生成反射实现类型查找
- 服务接口本身也需要运行时解析时,生成精确 type lookup
- 只有在 runtime 提供 `CqrsReflectionFallbackAttribute` 合同时,才允许发射依赖 fallback 的结果
如果当前编译环境缺少这个 fallback 合同,而某些 handler 又必须依赖它,生成器会报:
- `GF_Cqrs_001`
这条诊断的含义不是“某个 handler 写错了”,而是“当前 runtime 合同不足以安全承载这轮生成结果”。
## XML / API 阅读入口
如果你要核对生成器对外暴露的契约,优先看这些类型:
- `GFramework.Cqrs.ICqrsHandlerRegistry`
- `GFramework.Cqrs.CqrsHandlerRegistryAttribute`
- `GFramework.Cqrs.CqrsReflectionFallbackAttribute`
- `GFramework.Cqrs.SourceGenerators.Cqrs.CqrsHandlerRegistryGenerator`
模块族入口见:
- [../core/cqrs.md](../core/cqrs.md)
- [./index.md](./index.md)

View File

@ -65,7 +65,9 @@ GFramework 当前发布的生成器包是:
- 配置 schema 生成与运行时接法:
- [../game/config-system.md](../game/config-system.md)
- CQRS registry 生成入口:
- CQRS handler registry 生成器:
- [cqrs-handler-registry-generator](./cqrs-handler-registry-generator.md)
- CQRS 模块族采用入口:
- [../core/cqrs.md](../core/cqrs.md)
### Godot 专用生成器