mirror of
https://github.com/GeWuYou/GFramework.git
synced 2026-03-22 10:34:30 +08:00
Compare commits
144 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
63b1d71a0e | ||
|
|
cdc49c319a | ||
|
|
d94d8deb29 | ||
|
|
49609d3821 | ||
|
|
003fe42ad8 | ||
|
|
a42ec0c282 | ||
|
|
884249649d | ||
|
|
d582dffe40 | ||
|
|
63a6c2e6f0 | ||
|
|
f3d45169cd | ||
|
|
86645d34cb | ||
|
|
ab04f0ace7 | ||
|
|
51492b1dcd | ||
|
|
4caa3c0d71 | ||
|
|
fca3808657 | ||
|
|
5996ecf5f3 | ||
|
|
53edd13f8f | ||
|
|
0442fec2d1 | ||
|
|
2001eddbff | ||
|
|
3130a3bab2 | ||
|
|
ba4ee24ce7 | ||
|
|
dfae4ba207 | ||
|
|
ccb51791a3 | ||
|
|
55234c4d70 | ||
|
|
108bcbf27e | ||
|
|
51393c30ee | ||
|
|
589f9f7d63 | ||
|
|
ba8369c8b3 | ||
|
|
9ca28a44d8 | ||
|
|
0c5c9dceae | ||
|
|
d7e7d3cc7f | ||
|
|
b5c67850ce | ||
|
|
1f680d2822 | ||
|
|
075d397a4c | ||
|
|
5fb96761a3 | ||
|
|
e49713a842 | ||
|
|
aee13c3c1d | ||
|
|
05c4f06717 | ||
|
|
2accbf4bdf | ||
|
|
60068aff4f | ||
|
|
9c69c4ec00 | ||
|
|
65b949b62f | ||
|
|
4afa856fdc | ||
|
|
27858df94e | ||
|
|
1c2e68fc5a | ||
|
|
3d8e19b5e2 | ||
|
|
ef05713bf2 | ||
|
|
e022a10bd5 | ||
|
|
c82a15f8bc | ||
|
|
2d89efa4b7 | ||
|
|
597d4dfeda | ||
|
|
f3deb299ac | ||
|
|
fc2f9ebf1a | ||
|
|
0640a06e44 | ||
|
|
94f75bfa03 | ||
|
|
10640f1c73 | ||
|
|
cb0d0682b0 | ||
|
|
8b5efc69ec | ||
|
|
54103c21a4 | ||
|
|
7aa009ab06 | ||
|
|
90bfa7200a | ||
|
|
e4cc0c7943 | ||
|
|
0b7d5c8f0c | ||
|
|
920a2c519e | ||
|
|
f48a8db094 | ||
|
|
4362989056 | ||
|
|
1c30149ebd | ||
|
|
4156839bd9 | ||
|
|
d038b67e29 | ||
|
|
820cdcf0fa | ||
|
|
b01867b231 | ||
|
|
494c341c08 | ||
|
|
9c2e63f0e1 | ||
|
|
378d7afb23 | ||
|
|
00a687168f | ||
|
|
b6c13088cd | ||
|
|
ea79df232b | ||
|
|
ffda10be86 | ||
|
|
b37873a67c | ||
|
|
11c7bc1457 | ||
|
|
c6024bf94a | ||
|
|
248a29b4df | ||
|
|
1f0eb55288 | ||
|
|
caeb1ab80f | ||
|
|
4750910675 | ||
|
|
43b88e7573 | ||
|
|
8e4e794661 | ||
|
|
52f95c7e5f | ||
|
|
8ea462de28 | ||
|
|
95de78efae | ||
|
|
aeed1f903c | ||
|
|
027a214479 | ||
|
|
fb14d7122c | ||
|
|
53b04c12f0 | ||
|
|
f5d1985a59 | ||
|
|
05d7557fa1 | ||
|
|
f771b7dbef | ||
|
|
f35c9309f3 | ||
|
|
5c5525e3e9 | ||
|
|
ac2a9759e1 | ||
|
|
4257d58f86 | ||
|
|
bca92e52a3 | ||
|
|
af76e0ab0b | ||
|
|
23f186d395 | ||
|
|
25f7779b4e | ||
|
|
1b9e81bbdb | ||
|
|
5190b7a463 | ||
|
|
0d20a28385 | ||
|
|
eaa59c03c3 | ||
|
|
8a070af51b | ||
|
|
740cc66ac4 | ||
|
|
4804b75215 | ||
|
|
3dce243bcd | ||
|
|
6d398a515b | ||
|
|
575dcdf27b | ||
|
|
28ad02dc80 | ||
|
|
8554f01423 | ||
|
|
519e3a480b | ||
|
|
9edf64193f | ||
|
|
739565d278 | ||
|
|
a021941cab | ||
|
|
c969a9a022 | ||
|
|
84d7408bef | ||
|
|
b4ef62c731 | ||
|
|
b3838ce8c7 | ||
|
|
23f70a6e5a | ||
|
|
c5bd08acfd | ||
|
|
5ef464c484 | ||
|
|
e738e59a58 | ||
|
|
1b92bda8ba | ||
|
|
e5bd972ee7 | ||
|
|
74f27ddfd5 | ||
|
|
06114db8bd | ||
|
|
e5e3a1c0ca | ||
|
|
16d8cad4f3 | ||
|
|
330bd8b0b0 | ||
|
|
f8c39e46a5 | ||
|
|
b4d17edeee | ||
|
|
71b5831261 | ||
|
|
a5d3289f5c | ||
|
|
9deae03da0 | ||
|
|
6d67a125cb | ||
|
|
90796543b7 | ||
|
|
bbb91d597a |
62
.ai/environment/tools.ai.yaml
Normal file
62
.ai/environment/tools.ai.yaml
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
schema_version: 1
|
||||||
|
generated_at_utc: "2026-03-21T04:47:58Z"
|
||||||
|
generated_from: ".ai/environment/tools.raw.yaml"
|
||||||
|
generator: "scripts/generate-ai-environment.py"
|
||||||
|
platform:
|
||||||
|
family: "wsl-linux"
|
||||||
|
os: "Linux"
|
||||||
|
distro: "Ubuntu 24.04.4 LTS"
|
||||||
|
shell: "bash"
|
||||||
|
capabilities:
|
||||||
|
dotnet: true
|
||||||
|
python: true
|
||||||
|
node: true
|
||||||
|
bun: true
|
||||||
|
docker: true
|
||||||
|
fast_search: true
|
||||||
|
json_cli: true
|
||||||
|
tool_selection:
|
||||||
|
search:
|
||||||
|
preferred: "rg"
|
||||||
|
fallback: "grep"
|
||||||
|
use_for: "Repository text search."
|
||||||
|
json:
|
||||||
|
preferred: "jq"
|
||||||
|
fallback: "python3"
|
||||||
|
use_for: "Inspecting or transforming JSON command output."
|
||||||
|
shell:
|
||||||
|
preferred: "bash"
|
||||||
|
fallback: "sh"
|
||||||
|
use_for: "Repository shell scripts and command execution."
|
||||||
|
scripting:
|
||||||
|
preferred: "python3"
|
||||||
|
fallback: "bash"
|
||||||
|
use_for: "Non-trivial local automation and helper scripts."
|
||||||
|
docs_package_manager:
|
||||||
|
preferred: "bun"
|
||||||
|
fallback: "npm"
|
||||||
|
use_for: "Installing and previewing the docs site."
|
||||||
|
build_and_test:
|
||||||
|
preferred: "dotnet"
|
||||||
|
fallback: "unavailable"
|
||||||
|
use_for: "Build, test, restore, and solution validation."
|
||||||
|
python:
|
||||||
|
available: true
|
||||||
|
helper_packages:
|
||||||
|
requests: true
|
||||||
|
rich: true
|
||||||
|
openai: false
|
||||||
|
tiktoken: false
|
||||||
|
pydantic: false
|
||||||
|
pytest: false
|
||||||
|
preferences:
|
||||||
|
prefer_project_listed_tools: true
|
||||||
|
prefer_python_for_non_trivial_automation: true
|
||||||
|
avoid_unlisted_system_tools: true
|
||||||
|
rules:
|
||||||
|
- "Use rg instead of grep for repository search when rg is available."
|
||||||
|
- "Use jq for JSON inspection; fall back to python3 if jq is unavailable."
|
||||||
|
- "Prefer python3 over complex bash for non-trivial scripting when python3 is available."
|
||||||
|
- "Use bun for docs preview workflows when bun is available; otherwise fall back to npm."
|
||||||
|
- "Use dotnet for repository build and test workflows."
|
||||||
|
- "Do not assume unrelated system tools are part of the supported project environment."
|
||||||
89
.ai/environment/tools.raw.yaml
Normal file
89
.ai/environment/tools.raw.yaml
Normal file
@ -0,0 +1,89 @@
|
|||||||
|
schema_version: 1
|
||||||
|
generated_at_utc: "2026-03-21T04:47:28Z"
|
||||||
|
generator: "scripts/collect-dev-environment.sh"
|
||||||
|
|
||||||
|
platform:
|
||||||
|
os: "Linux"
|
||||||
|
distro: "Ubuntu 24.04.4 LTS"
|
||||||
|
version: "24.04"
|
||||||
|
kernel: "5.15.167.4-microsoft-standard-WSL2"
|
||||||
|
wsl: true
|
||||||
|
wsl_version: "2.4.13"
|
||||||
|
shell: "bash"
|
||||||
|
|
||||||
|
required_runtimes:
|
||||||
|
dotnet:
|
||||||
|
installed: true
|
||||||
|
version: "10.0.104"
|
||||||
|
path: "/usr/bin/dotnet"
|
||||||
|
purpose: "Builds and tests the GFramework solution."
|
||||||
|
python3:
|
||||||
|
installed: true
|
||||||
|
version: "Python 3.12.3"
|
||||||
|
path: "/usr/bin/python3"
|
||||||
|
purpose: "Runs local automation and environment collection scripts."
|
||||||
|
node:
|
||||||
|
installed: true
|
||||||
|
version: "v20.20.1"
|
||||||
|
path: "/usr/bin/node"
|
||||||
|
purpose: "Provides the JavaScript runtime used by docs tooling."
|
||||||
|
bun:
|
||||||
|
installed: true
|
||||||
|
version: "1.3.10"
|
||||||
|
path: "/root/.bun/bin/bun"
|
||||||
|
purpose: "Installs and previews the VitePress documentation site."
|
||||||
|
|
||||||
|
required_tools:
|
||||||
|
git:
|
||||||
|
installed: true
|
||||||
|
version: "git version 2.43.0"
|
||||||
|
path: "/usr/bin/git"
|
||||||
|
purpose: "Source control and patch review."
|
||||||
|
bash:
|
||||||
|
installed: true
|
||||||
|
version: "GNU bash, version 5.2.21(1)-release (x86_64-pc-linux-gnu)"
|
||||||
|
path: "/usr/bin/bash"
|
||||||
|
purpose: "Executes repository scripts and shell automation."
|
||||||
|
rg:
|
||||||
|
installed: true
|
||||||
|
version: "ripgrep 15.1.0 (rev af60c2de9d)"
|
||||||
|
path: "/root/.bun/install/global/node_modules/@openai/codex-linux-x64/vendor/x86_64-unknown-linux-musl/path/rg"
|
||||||
|
purpose: "Fast text search across the repository."
|
||||||
|
jq:
|
||||||
|
installed: true
|
||||||
|
version: "jq-1.7"
|
||||||
|
path: "/usr/bin/jq"
|
||||||
|
purpose: "Inspecting and transforming JSON outputs."
|
||||||
|
|
||||||
|
project_tools:
|
||||||
|
docker:
|
||||||
|
installed: true
|
||||||
|
version: "Docker version 29.2.1, build a5c7197"
|
||||||
|
path: "/usr/bin/docker"
|
||||||
|
purpose: "Runs MegaLinter and other containerized validation tools."
|
||||||
|
|
||||||
|
python_packages:
|
||||||
|
requests:
|
||||||
|
installed: true
|
||||||
|
version: "2.31.0"
|
||||||
|
purpose: "Simple HTTP calls in local helper scripts."
|
||||||
|
rich:
|
||||||
|
installed: true
|
||||||
|
version: "13.7.1"
|
||||||
|
purpose: "Readable CLI output for local Python helpers."
|
||||||
|
openai:
|
||||||
|
installed: false
|
||||||
|
version: "not-installed"
|
||||||
|
purpose: "Optional scripted access to OpenAI APIs."
|
||||||
|
tiktoken:
|
||||||
|
installed: false
|
||||||
|
version: "not-installed"
|
||||||
|
purpose: "Optional token counting for prompt and context inspection."
|
||||||
|
pydantic:
|
||||||
|
installed: false
|
||||||
|
version: "not-installed"
|
||||||
|
purpose: "Optional typed config and schema validation for helper scripts."
|
||||||
|
pytest:
|
||||||
|
installed: false
|
||||||
|
version: "not-installed"
|
||||||
|
purpose: "Optional lightweight testing for Python helper scripts."
|
||||||
205
.claude/skills/_shared/DOCUMENTATION_STANDARDS.md
Normal file
205
.claude/skills/_shared/DOCUMENTATION_STANDARDS.md
Normal file
@ -0,0 +1,205 @@
|
|||||||
|
# GFramework 文档编写规范
|
||||||
|
|
||||||
|
## Markdown 语法规范
|
||||||
|
|
||||||
|
### 1. 泛型标记转义
|
||||||
|
|
||||||
|
在 Markdown 文档中,所有泛型标记必须转义,否则会被 VitePress 误认为 HTML 标签。
|
||||||
|
|
||||||
|
**错误示例**:
|
||||||
|
```markdown
|
||||||
|
`Option<T>` 是一个泛型类型
|
||||||
|
`Result<TValue, TError>` 表示结果
|
||||||
|
public class Repository<TData> { }
|
||||||
|
```
|
||||||
|
|
||||||
|
**正确示例**:
|
||||||
|
```markdown
|
||||||
|
`Option<T>` 是一个泛型类型
|
||||||
|
`Result<TValue, TError>` 表示结果
|
||||||
|
public class Repository<TData> { }
|
||||||
|
```
|
||||||
|
|
||||||
|
**常见泛型标记**:
|
||||||
|
- `<T>` → `<T>`
|
||||||
|
- `<TResult>` → `<TResult>`
|
||||||
|
- `<TValue>` → `<TValue>`
|
||||||
|
- `<TError>` → `<TError>`
|
||||||
|
- `<TSaveData>` → `<TSaveData>`
|
||||||
|
- `<TData>` → `<TData>`
|
||||||
|
- `<TNode>` → `<TNode>`
|
||||||
|
|
||||||
|
### 2. HTML 标签转义
|
||||||
|
|
||||||
|
如果需要在文档中显示 HTML 标签,必须转义:
|
||||||
|
- `<summary>` → `<summary>`
|
||||||
|
- `<param>` → `<param>`
|
||||||
|
- `<returns>` → `<returns>`
|
||||||
|
|
||||||
|
### 3. 链接验证
|
||||||
|
|
||||||
|
**内部链接规则**:
|
||||||
|
- 使用相对路径: `/zh-CN/core/events`
|
||||||
|
- 确保目标文件存在
|
||||||
|
- 不要链接到尚未创建的页面
|
||||||
|
|
||||||
|
**已存在的文档路径**:
|
||||||
|
|
||||||
|
**Core 模块**:
|
||||||
|
- `/zh-CN/core/architecture` - 架构系统
|
||||||
|
- `/zh-CN/core/ioc` - IoC 容器
|
||||||
|
- `/zh-CN/core/events` - 事件系统
|
||||||
|
- `/zh-CN/core/command` - 命令系统
|
||||||
|
- `/zh-CN/core/query` - 查询系统
|
||||||
|
- `/zh-CN/core/model` - Model 系统
|
||||||
|
- `/zh-CN/core/system` - System 系统
|
||||||
|
- `/zh-CN/core/utility` - Utility 系统
|
||||||
|
- `/zh-CN/core/controller` - Controller 系统
|
||||||
|
- `/zh-CN/core/logging` - 日志系统
|
||||||
|
- `/zh-CN/core/pool` - 对象池
|
||||||
|
- `/zh-CN/core/property` - 可绑定属性
|
||||||
|
- `/zh-CN/core/lifecycle` - 生命周期管理
|
||||||
|
- `/zh-CN/core/coroutine` - 协程系统
|
||||||
|
- `/zh-CN/core/resource` - 资源管理
|
||||||
|
- `/zh-CN/core/state-machine` - 状态机
|
||||||
|
- `/zh-CN/core/cqrs` - CQRS 与 Mediator
|
||||||
|
- `/zh-CN/core/functional` - 函数式编程
|
||||||
|
- `/zh-CN/core/pause` - 暂停管理
|
||||||
|
- `/zh-CN/core/configuration` - 配置管理
|
||||||
|
- `/zh-CN/core/ecs` - ECS 系统集成
|
||||||
|
- `/zh-CN/core/extensions` - 扩展方法
|
||||||
|
- `/zh-CN/core/rule` - 规则系统
|
||||||
|
- `/zh-CN/core/environment` - 环境系统
|
||||||
|
- `/zh-CN/core/context` - 上下文系统
|
||||||
|
- `/zh-CN/core/async-initialization` - 异步初始化
|
||||||
|
|
||||||
|
**Game 模块**:
|
||||||
|
- `/zh-CN/game/scene` - 场景系统
|
||||||
|
- `/zh-CN/game/ui` - UI 系统
|
||||||
|
- `/zh-CN/game/data` - 数据与存档
|
||||||
|
- `/zh-CN/game/storage` - 存储系统
|
||||||
|
- `/zh-CN/game/serialization` - 序列化系统
|
||||||
|
- `/zh-CN/game/setting` - 设置系统
|
||||||
|
|
||||||
|
**Godot 模块**:
|
||||||
|
- `/zh-CN/godot/architecture` - Godot 架构集成
|
||||||
|
- `/zh-CN/godot/scene` - Godot 场景系统
|
||||||
|
- `/zh-CN/godot/ui` - Godot UI 系统
|
||||||
|
- `/zh-CN/godot/pool` - Godot 节点池
|
||||||
|
- `/zh-CN/godot/resource` - Godot 资源仓储
|
||||||
|
- `/zh-CN/godot/logging` - Godot 日志系统
|
||||||
|
- `/zh-CN/godot/pause` - Godot 暂停处理
|
||||||
|
- `/zh-CN/godot/extensions` - Godot 扩展
|
||||||
|
- `/zh-CN/godot/coroutine` - Godot 协程
|
||||||
|
- `/zh-CN/godot/signal` - Godot 信号
|
||||||
|
- `/zh-CN/godot/storage` - Godot 存储
|
||||||
|
|
||||||
|
**教程**:
|
||||||
|
- `/zh-CN/tutorials/coroutine-tutorial` - 协程系统教程
|
||||||
|
- `/zh-CN/tutorials/state-machine-tutorial` - 状态机教程
|
||||||
|
- `/zh-CN/tutorials/resource-management` - 资源管理教程
|
||||||
|
- `/zh-CN/tutorials/save-system` - 存档系统教程
|
||||||
|
- `/zh-CN/tutorials/godot-complete-project` - Godot 完整项目
|
||||||
|
- `/zh-CN/tutorials/functional-programming` - 函数式编程实践
|
||||||
|
- `/zh-CN/tutorials/pause-system` - 暂停系统实现
|
||||||
|
- `/zh-CN/tutorials/data-migration` - 数据迁移实践
|
||||||
|
- `/zh-CN/tutorials/godot-integration` - Godot 集成
|
||||||
|
- `/zh-CN/tutorials/advanced-patterns` - 高级模式
|
||||||
|
|
||||||
|
**其他**:
|
||||||
|
- `/zh-CN/getting-started/quick-start` - 快速开始
|
||||||
|
- `/zh-CN/getting-started/installation` - 安装指南
|
||||||
|
- `/zh-CN/best-practices/architecture-patterns` - 架构模式
|
||||||
|
|
||||||
|
**不存在的路径** (不要链接):
|
||||||
|
- `/zh-CN/best-practices/performance` - 尚未创建
|
||||||
|
- `/zh-CN/core/serializer` - 错误路径,应使用 `/zh-CN/game/serialization`
|
||||||
|
|
||||||
|
## 代码块规范
|
||||||
|
|
||||||
|
### 1. 代码块语言标识
|
||||||
|
|
||||||
|
始终指定代码块的语言:
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
\`\`\`csharp
|
||||||
|
public class Example { }
|
||||||
|
\`\`\`
|
||||||
|
|
||||||
|
\`\`\`bash
|
||||||
|
npm install
|
||||||
|
\`\`\`
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. 代码注释
|
||||||
|
|
||||||
|
代码示例应包含中文注释:
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
// 创建玩家实体
|
||||||
|
var player = new Player
|
||||||
|
{
|
||||||
|
Name = "玩家1", // 玩家名称
|
||||||
|
Level = 1 // 初始等级
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
## Frontmatter 规范
|
||||||
|
|
||||||
|
每个文档必须包含正确的 frontmatter:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
---
|
||||||
|
title: 文档标题
|
||||||
|
description: 简短描述(1-2 句话)
|
||||||
|
---
|
||||||
|
```
|
||||||
|
|
||||||
|
## 文档结构规范
|
||||||
|
|
||||||
|
### 指南文档结构
|
||||||
|
|
||||||
|
1. 概述
|
||||||
|
2. 核心概念
|
||||||
|
3. 基本用法
|
||||||
|
4. 高级用法
|
||||||
|
5. 最佳实践
|
||||||
|
6. 常见问题
|
||||||
|
7. 相关文档
|
||||||
|
|
||||||
|
### 教程文档结构
|
||||||
|
|
||||||
|
1. 学习目标
|
||||||
|
2. 前置条件
|
||||||
|
3. 步骤 1-N (3-7 步)
|
||||||
|
4. 完整代码
|
||||||
|
5. 运行结果
|
||||||
|
6. 下一步
|
||||||
|
7. 相关文档
|
||||||
|
|
||||||
|
## 验证清单
|
||||||
|
|
||||||
|
生成文档后,必须检查:
|
||||||
|
|
||||||
|
- [ ] 所有泛型标记已转义 (`<T>` → `<T>`)
|
||||||
|
- [ ] 所有内部链接指向存在的页面
|
||||||
|
- [ ] Frontmatter 格式正确
|
||||||
|
- [ ] 代码块指定了语言
|
||||||
|
- [ ] 代码包含中文注释
|
||||||
|
- [ ] 文档结构完整
|
||||||
|
- [ ] 没有 HTML 标签错误
|
||||||
|
|
||||||
|
## 自动修复脚本
|
||||||
|
|
||||||
|
如果文档已生成,可以使用以下脚本修复常见问题:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 修复泛型标记
|
||||||
|
sed -i 's/<T>/\<T\>/g' file.md
|
||||||
|
sed -i 's/<TResult>/\<TResult\>/g' file.md
|
||||||
|
sed -i 's/<TValue>/\<TValue\>/g' file.md
|
||||||
|
sed -i 's/<TError>/\<TError\>/g' file.md
|
||||||
|
|
||||||
|
# 验证构建
|
||||||
|
cd docs && bun run build
|
||||||
|
```
|
||||||
60
.github/workflows/ci.yml
vendored
60
.github/workflows/ci.yml
vendored
@ -13,8 +13,9 @@ permissions:
|
|||||||
security-events: write
|
security-events: write
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
test:
|
# 代码质量检查 job(并行执行,不阻塞构建)
|
||||||
name: Build and Test
|
code-quality:
|
||||||
|
name: Code Quality & Security
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
@ -23,6 +24,11 @@ jobs:
|
|||||||
uses: actions/checkout@v6
|
uses: actions/checkout@v6
|
||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
|
|
||||||
|
# 校验C#命名空间与源码目录是否符合命名规范
|
||||||
|
- name: Validate C# naming
|
||||||
|
run: bash scripts/validate-csharp-naming.sh
|
||||||
|
|
||||||
# 缓存MegaLinter
|
# 缓存MegaLinter
|
||||||
- name: Cache MegaLinter
|
- name: Cache MegaLinter
|
||||||
uses: actions/cache@v5
|
uses: actions/cache@v5
|
||||||
@ -31,21 +37,22 @@ jobs:
|
|||||||
key: ${{ runner.os }}-megalinter-v9
|
key: ${{ runner.os }}-megalinter-v9
|
||||||
restore-keys: |
|
restore-keys: |
|
||||||
${{ runner.os }}-megalinter-
|
${{ runner.os }}-megalinter-
|
||||||
|
|
||||||
|
|
||||||
# MegaLinter扫描步骤
|
# MegaLinter扫描步骤
|
||||||
# 执行代码质量检查和安全扫描,生成SARIF格式报告
|
# 执行代码质量检查和安全扫描,生成SARIF格式报告
|
||||||
- name: MegaLinter
|
- name: MegaLinter
|
||||||
uses: oxsecurity/megalinter@v9.3.0
|
uses: oxsecurity/megalinter@v9.4.0
|
||||||
continue-on-error: true
|
continue-on-error: true
|
||||||
env:
|
env:
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
FAIL_ON_ERROR: ${{ github.ref == 'refs/heads/main' }}
|
FAIL_ON_ERROR: ${{ github.ref == 'refs/heads/main' }}
|
||||||
|
|
||||||
# 上传SARIF格式的安全和代码质量问题报告到GitHub安全中心
|
# 上传SARIF格式的安全和代码质量问题报告到GitHub安全中心
|
||||||
- name: Upload SARIF
|
- name: Upload SARIF
|
||||||
uses: github/codeql-action/upload-sarif@v4
|
uses: github/codeql-action/upload-sarif@v4
|
||||||
with:
|
with:
|
||||||
sarif_file: megalinter-reports/sarif
|
sarif_file: megalinter-reports/sarif
|
||||||
|
|
||||||
# 缓存TruffleHog
|
# 缓存TruffleHog
|
||||||
- name: Cache TruffleHog
|
- name: Cache TruffleHog
|
||||||
uses: actions/cache@v5
|
uses: actions/cache@v5
|
||||||
@ -57,7 +64,7 @@ jobs:
|
|||||||
# 使用 TruffleHog 工具扫描代码库中的敏感信息泄露,如API密钥、密码等
|
# 使用 TruffleHog 工具扫描代码库中的敏感信息泄露,如API密钥、密码等
|
||||||
# 该步骤会比较基础分支和当前提交之间的差异,检测新增内容中是否包含敏感数据
|
# 该步骤会比较基础分支和当前提交之间的差异,检测新增内容中是否包含敏感数据
|
||||||
- name: TruffleHog OSS
|
- name: TruffleHog OSS
|
||||||
uses: trufflesecurity/trufflehog@v3.93.4
|
uses: trufflesecurity/trufflehog@v3.93.8
|
||||||
with:
|
with:
|
||||||
# 扫描路径,. 表示扫描整个仓库
|
# 扫描路径,. 表示扫描整个仓库
|
||||||
path: .
|
path: .
|
||||||
@ -65,6 +72,18 @@ jobs:
|
|||||||
base: ${{ github.event.before }}
|
base: ${{ github.event.before }}
|
||||||
# 当前提交哈希,作为扫描的目标版本
|
# 当前提交哈希,作为扫描的目标版本
|
||||||
head: ${{ github.sha }}
|
head: ${{ github.sha }}
|
||||||
|
|
||||||
|
# 构建和测试 job(并行执行)
|
||||||
|
build-and-test:
|
||||||
|
name: Build and Test
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
steps:
|
||||||
|
# 检出源代码
|
||||||
|
- name: Checkout code
|
||||||
|
uses: actions/checkout@v6
|
||||||
|
with:
|
||||||
|
fetch-depth: 0
|
||||||
|
|
||||||
# 安装和配置.NET SDK版本
|
# 安装和配置.NET SDK版本
|
||||||
- name: Setup .NET 8
|
- name: Setup .NET 8
|
||||||
@ -110,21 +129,36 @@ jobs:
|
|||||||
run: dotnet build -c Release --no-restore
|
run: dotnet build -c Release --no-restore
|
||||||
|
|
||||||
# 运行单元测试,输出TRX格式结果到TestResults目录
|
# 运行单元测试,输出TRX格式结果到TestResults目录
|
||||||
- name: Test - Core
|
# 在同一个 step 中并发执行所有测试以加快速度
|
||||||
|
- name: Test All Projects
|
||||||
run: |
|
run: |
|
||||||
dotnet test GFramework.Core.Tests \
|
dotnet test GFramework.Core.Tests \
|
||||||
-c Release \
|
-c Release \
|
||||||
--no-build \
|
--no-build \
|
||||||
--logger "trx;LogFileName=core-$RANDOM.trx" \
|
--logger "trx;LogFileName=core-$RANDOM.trx" \
|
||||||
--results-directory TestResults
|
--results-directory TestResults &
|
||||||
|
|
||||||
- name: Test - SourceGenerators
|
dotnet test GFramework.Game.Tests \
|
||||||
run: |
|
-c Release \
|
||||||
|
--no-build \
|
||||||
|
--logger "trx;LogFileName=game-$RANDOM.trx" \
|
||||||
|
--results-directory TestResults &
|
||||||
|
|
||||||
dotnet test GFramework.SourceGenerators.Tests \
|
dotnet test GFramework.SourceGenerators.Tests \
|
||||||
-c Release \
|
-c Release \
|
||||||
--no-build \
|
--no-build \
|
||||||
--logger "trx;LogFileName=sg-$RANDOM.trx" \
|
--logger "trx;LogFileName=sg-$RANDOM.trx" \
|
||||||
--results-directory TestResults
|
--results-directory TestResults &
|
||||||
|
|
||||||
|
dotnet test GFramework.Ecs.Arch.Tests \
|
||||||
|
-c Release \
|
||||||
|
--no-build \
|
||||||
|
--logger "trx;LogFileName=ecs-arch-$RANDOM.trx" \
|
||||||
|
--results-directory TestResults &
|
||||||
|
|
||||||
|
# 等待所有后台测试完成
|
||||||
|
wait
|
||||||
|
|
||||||
- name: Generate CTRF report
|
- name: Generate CTRF report
|
||||||
run: |
|
run: |
|
||||||
mkdir -p ctrf
|
mkdir -p ctrf
|
||||||
@ -164,4 +198,4 @@ jobs:
|
|||||||
fetch-previous-results: true
|
fetch-previous-results: true
|
||||||
env:
|
env:
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
if: always()
|
if: always()
|
||||||
|
|||||||
2
.github/workflows/license-compliance.yml
vendored
2
.github/workflows/license-compliance.yml
vendored
@ -59,7 +59,7 @@ jobs:
|
|||||||
# name: 工件名称,用于标识上传的文件集合
|
# name: 工件名称,用于标识上传的文件集合
|
||||||
# path: 指定需要上传的文件路径列表(支持多行格式)
|
# path: 指定需要上传的文件路径列表(支持多行格式)
|
||||||
- name: Upload compliance artifacts
|
- name: Upload compliance artifacts
|
||||||
uses: actions/upload-artifact@v6
|
uses: actions/upload-artifact@v7
|
||||||
with:
|
with:
|
||||||
name: license-compliance
|
name: license-compliance
|
||||||
path: |
|
path: |
|
||||||
|
|||||||
2
.github/workflows/publish.yml
vendored
2
.github/workflows/publish.yml
vendored
@ -69,7 +69,7 @@ jobs:
|
|||||||
dotnet pack -c Release -o ./packages -p:PackageVersion=${{ steps.tag_version.outputs.version }} -p:IncludeSymbols=false
|
dotnet pack -c Release -o ./packages -p:PackageVersion=${{ steps.tag_version.outputs.version }} -p:IncludeSymbols=false
|
||||||
# 上传许可证合规相关的工件文件,包括通知文件、第三方许可证、SBOM文件及验证结果
|
# 上传许可证合规相关的工件文件,包括通知文件、第三方许可证、SBOM文件及验证结果
|
||||||
- name: Upload compliance artifacts
|
- name: Upload compliance artifacts
|
||||||
uses: actions/upload-artifact@v6
|
uses: actions/upload-artifact@v7
|
||||||
with:
|
with:
|
||||||
name: license-compliance
|
name: license-compliance
|
||||||
path: |
|
path: |
|
||||||
|
|||||||
10
.gitignore
vendored
10
.gitignore
vendored
@ -5,5 +5,13 @@ riderModule.iml
|
|||||||
/_ReSharper.Caches/
|
/_ReSharper.Caches/
|
||||||
GFramework.sln.DotSettings.user
|
GFramework.sln.DotSettings.user
|
||||||
.idea/
|
.idea/
|
||||||
|
# ai
|
||||||
opencode.json
|
opencode.json
|
||||||
.claude/settings.local.json
|
.claude/settings.local.json
|
||||||
|
.claude/settings.json
|
||||||
|
.omc/
|
||||||
|
docs/.omc/
|
||||||
|
docs/.vitepress/cache/
|
||||||
|
local-plan/
|
||||||
|
# tool
|
||||||
|
.venv/
|
||||||
220
AGENTS.md
Normal file
220
AGENTS.md
Normal file
@ -0,0 +1,220 @@
|
|||||||
|
# AGENTS.md
|
||||||
|
|
||||||
|
This document is the single source of truth for coding behavior in this repository.
|
||||||
|
|
||||||
|
All AI agents and contributors must follow these rules when writing, reviewing, or modifying code in `GFramework`.
|
||||||
|
|
||||||
|
## Environment Capability Inventory
|
||||||
|
|
||||||
|
- Before choosing runtimes or CLI tools, read `@.ai/environment/tools.ai.yaml`.
|
||||||
|
- 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.
|
||||||
|
|
||||||
|
## Commenting Rules (MUST)
|
||||||
|
|
||||||
|
All generated or modified code MUST include clear and meaningful comments where required by the rules below.
|
||||||
|
|
||||||
|
### XML Documentation (Required)
|
||||||
|
|
||||||
|
- All public, protected, and internal types and members MUST include XML documentation comments (`///`).
|
||||||
|
- Use `<summary>`, `<param>`, `<returns>`, `<exception>`, and `<remarks>` where applicable.
|
||||||
|
- Comments must explain intent, contract, and usage constraints instead of restating syntax.
|
||||||
|
- If a member participates in lifecycle, threading, registration, or disposal behavior, document that behavior
|
||||||
|
explicitly.
|
||||||
|
|
||||||
|
### Inline Comments
|
||||||
|
|
||||||
|
- Add inline comments for:
|
||||||
|
- Non-trivial logic
|
||||||
|
- Concurrency or threading behavior
|
||||||
|
- Performance-sensitive paths
|
||||||
|
- Workarounds, compatibility constraints, or edge cases
|
||||||
|
- Registration order, lifecycle sequencing, or generated code assumptions
|
||||||
|
- Avoid obvious comments such as `// increment i`.
|
||||||
|
|
||||||
|
### Architecture-Level Comments
|
||||||
|
|
||||||
|
- Core framework components such as Architecture, Module, System, Context, Registry, Service Module, and Lifecycle types
|
||||||
|
MUST include high-level explanations of:
|
||||||
|
- Responsibilities
|
||||||
|
- Lifecycle
|
||||||
|
- Interaction with other components
|
||||||
|
- Why the abstraction exists
|
||||||
|
- When to use it instead of alternatives
|
||||||
|
|
||||||
|
### Source Generator Comments
|
||||||
|
|
||||||
|
- Generated logic and generator pipelines MUST explain:
|
||||||
|
- What is generated
|
||||||
|
- Why it is generated
|
||||||
|
- The semantic assumptions the generator relies on
|
||||||
|
- Any diagnostics or fallback behavior
|
||||||
|
|
||||||
|
### Complex Logic Requirement
|
||||||
|
|
||||||
|
- Methods with non-trivial logic MUST document:
|
||||||
|
- The core idea
|
||||||
|
- Key decisions
|
||||||
|
- Edge case handling, if any
|
||||||
|
|
||||||
|
### Quality Rules
|
||||||
|
|
||||||
|
- Comments MUST NOT be trivial, redundant, or misleading.
|
||||||
|
- Prefer explaining `why` and `when`, not just `what`.
|
||||||
|
- Code should remain understandable without requiring external context.
|
||||||
|
- Prefer slightly more explanation over too little for framework code.
|
||||||
|
|
||||||
|
### Enforcement
|
||||||
|
|
||||||
|
- Missing required documentation is a coding standards violation.
|
||||||
|
- Code that does not meet the documentation rules is considered incomplete.
|
||||||
|
|
||||||
|
## Code Style
|
||||||
|
|
||||||
|
### Language and Project Settings
|
||||||
|
|
||||||
|
- Follow the repository defaults:
|
||||||
|
- `ImplicitUsings` disabled
|
||||||
|
- `Nullable` enabled
|
||||||
|
- `GenerateDocumentationFile` enabled for shipped libraries
|
||||||
|
- `LangVersion` is generally `preview` in the main libraries and abstractions
|
||||||
|
- Do not rely on implicit imports. Declare every required `using` explicitly.
|
||||||
|
- Write null-safe code that respects nullable annotations instead of suppressing warnings by default.
|
||||||
|
|
||||||
|
### Naming and Structure
|
||||||
|
|
||||||
|
- Use the namespace pattern `GFramework.{Module}.{Feature}` with PascalCase segments.
|
||||||
|
- Follow standard C# naming:
|
||||||
|
- Types, methods, properties, events, and constants: PascalCase
|
||||||
|
- Interfaces: `I` prefix
|
||||||
|
- Parameters and locals: camelCase
|
||||||
|
- Private fields: `_camelCase`
|
||||||
|
- Keep abstractions projects free of implementation details and engine-specific dependencies.
|
||||||
|
- Preserve existing module boundaries. Do not introduce new cross-module dependencies without clear architectural need.
|
||||||
|
|
||||||
|
### Formatting
|
||||||
|
|
||||||
|
- Use 4 spaces for indentation. Do not use tabs.
|
||||||
|
- Use Allman braces.
|
||||||
|
- Keep `using` directives at the top of the file and sort them consistently.
|
||||||
|
- Separate logical blocks with blank lines when it improves readability.
|
||||||
|
- Prefer one primary type per file unless the surrounding project already uses a different local pattern.
|
||||||
|
- Keep line length readable. Around 120 characters is the preferred upper bound.
|
||||||
|
|
||||||
|
### C# Conventions
|
||||||
|
|
||||||
|
- Prefer explicit, readable code over clever shorthand in framework internals.
|
||||||
|
- Match existing async patterns and naming conventions (`Async` suffix for asynchronous methods).
|
||||||
|
- Avoid hidden side effects in property getters, constructors, and registration helpers.
|
||||||
|
- Preserve deterministic behavior in registries, lifecycle orchestration, and generated outputs.
|
||||||
|
- When adding analyzers or suppressions, keep them minimal and justify them in code comments if the reason is not
|
||||||
|
obvious.
|
||||||
|
|
||||||
|
### Analyzer and Validation Expectations
|
||||||
|
|
||||||
|
- The repository uses `Meziantou.Analyzer`; treat analyzer feedback as part of the coding standard.
|
||||||
|
- Naming must remain compatible with `scripts/validate-csharp-naming.sh`.
|
||||||
|
|
||||||
|
## Testing Requirements
|
||||||
|
|
||||||
|
### Required Coverage
|
||||||
|
|
||||||
|
- Every non-trivial feature, bug fix, or behavior change MUST include tests or an explicit justification for why a test
|
||||||
|
is not practical.
|
||||||
|
- Public API changes must be covered by unit or integration tests.
|
||||||
|
- Regression fixes should include a test that fails before the fix and passes after it.
|
||||||
|
|
||||||
|
### Test Organization
|
||||||
|
|
||||||
|
- Mirror the source structure in test projects whenever practical.
|
||||||
|
- Reuse existing architecture test infrastructure when relevant:
|
||||||
|
- `ArchitectureTestsBase<T>`
|
||||||
|
- `SyncTestArchitecture`
|
||||||
|
- `AsyncTestArchitecture`
|
||||||
|
- Keep tests focused on observable behavior, not implementation trivia.
|
||||||
|
|
||||||
|
### Source Generator Tests
|
||||||
|
|
||||||
|
- Source generator changes MUST be covered by generator tests.
|
||||||
|
- Preserve snapshot-based verification patterns already used in the repository.
|
||||||
|
- When generator behavior changes intentionally, update snapshots together with the implementation.
|
||||||
|
|
||||||
|
### Validation Commands
|
||||||
|
|
||||||
|
Use the smallest command set that proves the change, then expand if the change is cross-cutting.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Build the full solution
|
||||||
|
dotnet build GFramework.sln -c Release
|
||||||
|
|
||||||
|
# Run all tests
|
||||||
|
dotnet test GFramework.sln -c Release
|
||||||
|
|
||||||
|
# Run a single test project
|
||||||
|
dotnet test GFramework.Core.Tests -c Release
|
||||||
|
dotnet test GFramework.Game.Tests -c Release
|
||||||
|
dotnet test GFramework.SourceGenerators.Tests -c Release
|
||||||
|
dotnet test GFramework.Ecs.Arch.Tests -c Release
|
||||||
|
|
||||||
|
# Run a single NUnit test or test group
|
||||||
|
dotnet test GFramework.Core.Tests -c Release --filter "FullyQualifiedName~CommandExecutorTests.Execute"
|
||||||
|
|
||||||
|
# Validate naming rules used by CI
|
||||||
|
bash scripts/validate-csharp-naming.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
### Test Execution Expectations
|
||||||
|
|
||||||
|
- Run targeted tests for the code you changed whenever possible.
|
||||||
|
- Run broader solution-level validation for changes that touch shared abstractions, lifecycle behavior, source
|
||||||
|
generators, or dependency wiring.
|
||||||
|
- Do not claim completion if required tests were skipped; state what was not run and why.
|
||||||
|
|
||||||
|
## Security Rules
|
||||||
|
|
||||||
|
- Validate external or user-controlled input before it reaches file system, serialization, reflection, code generation,
|
||||||
|
or process boundaries.
|
||||||
|
- Do not build command strings, file paths, type names, or generated code from untrusted input without strict validation
|
||||||
|
or allow-listing.
|
||||||
|
- Avoid logging secrets, tokens, credentials, or machine-specific sensitive data.
|
||||||
|
- Keep source generators deterministic and free of hidden environment or network dependencies.
|
||||||
|
- Prefer least-privilege behavior for file, process, and environment access.
|
||||||
|
- Do not introduce unsafe deserialization, broad reflection-based activation, or dynamic code execution unless it is
|
||||||
|
explicitly required and tightly constrained.
|
||||||
|
- When adding caching, pooling, or shared mutable state, document thread-safety assumptions and failure modes.
|
||||||
|
- Minimize new package dependencies. Add them only when necessary and keep scope narrow.
|
||||||
|
|
||||||
|
## Documentation Rules
|
||||||
|
|
||||||
|
### Code Documentation
|
||||||
|
|
||||||
|
- Any change to public API, lifecycle semantics, module behavior, or extension points MUST update the related XML docs.
|
||||||
|
- If a framework abstraction changes meaning or intended usage, update the explanatory comments in code as part of the
|
||||||
|
same change.
|
||||||
|
|
||||||
|
### Repository Documentation
|
||||||
|
|
||||||
|
- Update the relevant `README.md` or `docs/` page when behavior, setup steps, architecture guidance, or user-facing
|
||||||
|
examples change.
|
||||||
|
- The main documentation site lives under `docs/`, with Chinese content under `docs/zh-CN/`.
|
||||||
|
- Keep code samples, package names, and command examples aligned with the current repository state.
|
||||||
|
- Prefer documenting behavior and design intent, not only API surface.
|
||||||
|
|
||||||
|
### Documentation Preview
|
||||||
|
|
||||||
|
When documentation changes need local preview, use:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd docs && bun install && bun run dev
|
||||||
|
```
|
||||||
|
|
||||||
|
## Review Standard
|
||||||
|
|
||||||
|
Before considering work complete, confirm:
|
||||||
|
|
||||||
|
- Required comments and XML docs are present
|
||||||
|
- Code follows repository style and naming rules
|
||||||
|
- Relevant tests were added or updated
|
||||||
|
- Sensitive or unsafe behavior was not introduced
|
||||||
|
- User-facing documentation is updated when needed
|
||||||
134
CLAUDE.md
Normal file
134
CLAUDE.md
Normal file
@ -0,0 +1,134 @@
|
|||||||
|
# CLAUDE.md
|
||||||
|
|
||||||
|
This file provides project understanding for AI agents working in this repository.
|
||||||
|
|
||||||
|
## Project Overview
|
||||||
|
|
||||||
|
GFramework 是面向游戏开发的模块化 C# 框架,核心能力与引擎解耦。项目灵感参考 QFramework,并在模块边界、工程组织和可扩展性方面持续重构。
|
||||||
|
|
||||||
|
## AI Agent Instructions
|
||||||
|
|
||||||
|
All coding rules are defined in:
|
||||||
|
|
||||||
|
@AGENTS.md
|
||||||
|
|
||||||
|
Follow them strictly.
|
||||||
|
|
||||||
|
## Module Dependency Graph
|
||||||
|
|
||||||
|
```text
|
||||||
|
GFramework (meta package) ─→ Core + Game
|
||||||
|
GFramework.Core ─→ Core.Abstractions
|
||||||
|
GFramework.Game ─→ Game.Abstractions, Core, Core.Abstractions
|
||||||
|
GFramework.Godot ─→ Core, Game, Core.Abstractions, Game.Abstractions
|
||||||
|
GFramework.Ecs.Arch ─→ Ecs.Arch.Abstractions, Core, Core.Abstractions
|
||||||
|
GFramework.SourceGenerators ─→ SourceGenerators.Common, SourceGenerators.Abstractions
|
||||||
|
```
|
||||||
|
|
||||||
|
- **Abstractions projects** (`netstandard2.1`): 只包含接口和契约定义,不承载运行时实现逻辑。
|
||||||
|
- **Core / Game / Ecs.Arch** (`net8.0;net9.0;net10.0`): 平台无关的核心实现层。
|
||||||
|
- **Godot**: Godot 引擎集成层,负责与节点、场景和引擎生命周期对接。
|
||||||
|
- **SourceGenerators** (`netstandard2.1`): Roslyn 增量源码生成器及其公共基础设施。
|
||||||
|
|
||||||
|
## Architecture Pattern
|
||||||
|
|
||||||
|
框架核心采用 `Architecture / Model / System / Utility` 四层结构:
|
||||||
|
|
||||||
|
- **IArchitecture**: 顶层容器,负责生命周期管理、组件注册、模块安装和统一服务访问。
|
||||||
|
- **IContextAware**: 统一上下文访问接口,组件通过 `SetContext(IArchitectureContext)` 获取架构上下文。
|
||||||
|
- **IModel**: 数据与状态层,负责长期状态和业务数据建模。
|
||||||
|
- **ISystem**: 业务逻辑层,负责命令执行、流程编排和规则落地。
|
||||||
|
- **IUtility**: 通用无状态工具层,供其他层复用。
|
||||||
|
|
||||||
|
关键实现位于 `GFramework.Core/Architectures/Architecture.cs`,其职责是作为总协调器串联生命周期、组件注册和模块系统。
|
||||||
|
|
||||||
|
## Architecture Details
|
||||||
|
|
||||||
|
### Lifecycle
|
||||||
|
|
||||||
|
Architecture 负责统一生命周期编排,核心阶段包括:
|
||||||
|
|
||||||
|
- `Init`
|
||||||
|
- `Ready`
|
||||||
|
- `Destroy`
|
||||||
|
|
||||||
|
在实现层中,生命周期被拆分为更细粒度的初始化与销毁阶段,用于保证 Utility、Model、System、服务模块和钩子的顺序一致性。
|
||||||
|
|
||||||
|
### Component Coordination
|
||||||
|
|
||||||
|
框架通过独立组件协作完成架构编排:
|
||||||
|
|
||||||
|
- `ArchitectureLifecycle`: 管理生命周期阶段、阶段转换和生命周期钩子。
|
||||||
|
- `ArchitectureComponentRegistry`: 管理 Model、System、Utility 的注册与解析。
|
||||||
|
- `ArchitectureModules`: 管理模块安装、服务模块接入和扩展点注册。
|
||||||
|
|
||||||
|
这组拆分的目标是降低单个核心类的职责密度,同时保持对外 API 稳定。
|
||||||
|
|
||||||
|
### Context Propagation
|
||||||
|
|
||||||
|
`IArchitectureContext` 和相关 Provider 类型负责在组件之间传播上下文能力,使 Model、System
|
||||||
|
和外部扩展都能通过统一入口访问架构服务,而不直接耦合具体实现细节。
|
||||||
|
|
||||||
|
## Key Patterns
|
||||||
|
|
||||||
|
### CQRS
|
||||||
|
|
||||||
|
命令与查询分离,支持同步与异步执行。Mediator 模式通过源码生成器集成,以减少模板代码并保持调用路径清晰。
|
||||||
|
|
||||||
|
### EventBus
|
||||||
|
|
||||||
|
类型安全事件总线支持事件发布、订阅、优先级、过滤器和弱引用订阅。它是模块之间松耦合通信的核心基础设施之一。
|
||||||
|
|
||||||
|
### BindableProperty
|
||||||
|
|
||||||
|
响应式属性模型通过值变化通知驱动界面或业务层更新,适合表达轻量级状态同步。
|
||||||
|
|
||||||
|
### Coroutine
|
||||||
|
|
||||||
|
帧驱动协程系统基于 `IYieldInstruction` 和调度器抽象,支持等待时间、事件和任务完成等常见模式。
|
||||||
|
|
||||||
|
### IoC
|
||||||
|
|
||||||
|
依赖注入通过 `MicrosoftDiContainer` 对 `Microsoft.Extensions.DependencyInjection` 进行封装,用于统一组件注册和服务解析体验。
|
||||||
|
|
||||||
|
### Service Modules
|
||||||
|
|
||||||
|
`IServiceModule` 模式用于向 Architecture 注册内置服务,例如 EventBus、CommandExecutor、QueryExecutor 等。这一模式承担“基础设施能力装配”的职责。
|
||||||
|
|
||||||
|
## Source Generators
|
||||||
|
|
||||||
|
当前仓库包含多类 Roslyn 增量源码生成器:
|
||||||
|
|
||||||
|
- `LoggerGenerator` (`[Log]`): 自动生成日志字段和日志辅助方法。
|
||||||
|
- `PriorityGenerator` (`[Priority]`): 生成优先级比较相关实现。
|
||||||
|
- `EnumExtensionsGenerator` (`[GenerateEnumExtensions]`): 生成枚举扩展能力。
|
||||||
|
- `ContextAwareGenerator` (`[ContextAware]`): 自动实现 `IContextAware` 相关样板逻辑。
|
||||||
|
|
||||||
|
这些生成器的目标是减少重复代码,同时保持框架层 API 的一致性与可维护性。
|
||||||
|
|
||||||
|
## Module Structure
|
||||||
|
|
||||||
|
仓库以“抽象层 + 实现层 + 集成层 + 生成器层”的方式组织:
|
||||||
|
|
||||||
|
- `GFramework.Core.Abstractions` / `GFramework.Game.Abstractions`: 约束接口和公共契约。
|
||||||
|
- `GFramework.Core` / `GFramework.Game`: 提供平台无关实现。
|
||||||
|
- `GFramework.Godot`: 提供与 Godot 运行时集成的适配实现。
|
||||||
|
- `GFramework.Ecs.Arch`: 提供 ECS Architecture 相关扩展。
|
||||||
|
- `GFramework.SourceGenerators` 及相关 Abstractions/Common: 提供代码生成能力。
|
||||||
|
|
||||||
|
这种结构的核心设计目标是让抽象稳定、实现可替换、引擎集成隔离、生成器能力可独立演进。
|
||||||
|
|
||||||
|
## Documentation Structure
|
||||||
|
|
||||||
|
项目文档位于 `docs/`,中文内容位于 `docs/zh-CN/`。文档内容覆盖:
|
||||||
|
|
||||||
|
- 入门与安装
|
||||||
|
- Core / Game / Godot / ECS 各模块能力
|
||||||
|
- Source Generator 使用说明
|
||||||
|
- 教程、最佳实践与故障排查
|
||||||
|
|
||||||
|
阅读顺序通常建议先看根目录 `README.md` 和各子模块 `README.md`,再进入 `docs/` 查阅专题说明。
|
||||||
|
|
||||||
|
## Design Intent
|
||||||
|
|
||||||
|
GFramework 的设计重点不是把所有能力堆进单一核心类,而是通过清晰的模块边界、可组合的服务注册方式、稳定的抽象契约以及适度自动化的源码生成,构建一个适合长期演进的游戏开发基础框架。
|
||||||
@ -0,0 +1,42 @@
|
|||||||
|
using System.Collections.Concurrent;
|
||||||
|
|
||||||
|
namespace GFramework.Core.Abstractions.Architectures;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 架构模块注册表 - 用于外部模块的自动注册
|
||||||
|
/// </summary>
|
||||||
|
public static class ArchitectureModuleRegistry
|
||||||
|
{
|
||||||
|
private static readonly ConcurrentDictionary<string, Func<IServiceModule>> Factories = new(StringComparer.Ordinal);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 注册模块工厂(幂等操作,相同模块名只会注册一次)
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="factory">模块工厂函数</param>
|
||||||
|
public static void Register(Func<IServiceModule> factory)
|
||||||
|
{
|
||||||
|
// 创建临时实例以获取模块名(用于幂等性检查)
|
||||||
|
var tempModule = factory();
|
||||||
|
var moduleName = tempModule.ModuleName;
|
||||||
|
|
||||||
|
// 幂等注册:相同模块名只注册一次
|
||||||
|
Factories.TryAdd(moduleName, factory);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 创建所有已注册的模块实例
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>模块实例集合</returns>
|
||||||
|
public static IEnumerable<IServiceModule> CreateModules()
|
||||||
|
{
|
||||||
|
return Factories.Values.Select(f => f());
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 清空注册表(主要用于测试)
|
||||||
|
/// </summary>
|
||||||
|
public static void Clear()
|
||||||
|
{
|
||||||
|
Factories.Clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,10 +1,10 @@
|
|||||||
using GFramework.Core.Abstractions.lifecycle;
|
using GFramework.Core.Abstractions.Lifecycle;
|
||||||
using GFramework.Core.Abstractions.model;
|
using GFramework.Core.Abstractions.Model;
|
||||||
using GFramework.Core.Abstractions.system;
|
using GFramework.Core.Abstractions.Systems;
|
||||||
using GFramework.Core.Abstractions.utility;
|
using GFramework.Core.Abstractions.Utility;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
|
||||||
namespace GFramework.Core.Abstractions.architecture;
|
namespace GFramework.Core.Abstractions.Architectures;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 架构接口,专注于生命周期管理,包括系统、模型、工具的注册和获取
|
/// 架构接口,专注于生命周期管理,包括系统、模型、工具的注册和获取
|
||||||
@ -1,6 +1,6 @@
|
|||||||
using GFramework.Core.Abstractions.properties;
|
using GFramework.Core.Abstractions.Properties;
|
||||||
|
|
||||||
namespace GFramework.Core.Abstractions.architecture;
|
namespace GFramework.Core.Abstractions.Architectures;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 定义架构配置的接口,提供日志工厂、日志级别和架构选项的配置功能
|
/// 定义架构配置的接口,提供日志工厂、日志级别和架构选项的配置功能
|
||||||
@ -1,14 +1,14 @@
|
|||||||
using GFramework.Core.Abstractions.command;
|
using GFramework.Core.Abstractions.Command;
|
||||||
using GFramework.Core.Abstractions.environment;
|
using GFramework.Core.Abstractions.Environment;
|
||||||
using GFramework.Core.Abstractions.events;
|
using GFramework.Core.Abstractions.Events;
|
||||||
using GFramework.Core.Abstractions.model;
|
using GFramework.Core.Abstractions.Model;
|
||||||
using GFramework.Core.Abstractions.query;
|
using GFramework.Core.Abstractions.Query;
|
||||||
using GFramework.Core.Abstractions.system;
|
using GFramework.Core.Abstractions.Systems;
|
||||||
using GFramework.Core.Abstractions.utility;
|
using GFramework.Core.Abstractions.Utility;
|
||||||
using Mediator;
|
using Mediator;
|
||||||
using ICommand = GFramework.Core.Abstractions.command.ICommand;
|
using ICommand = GFramework.Core.Abstractions.Command.ICommand;
|
||||||
|
|
||||||
namespace GFramework.Core.Abstractions.architecture;
|
namespace GFramework.Core.Abstractions.Architectures;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 架构上下文接口,提供对系统、模型、工具类的访问以及命令、查询、事件的发送和注册功能
|
/// 架构上下文接口,提供对系统、模型、工具类的访问以及命令、查询、事件的发送和注册功能
|
||||||
@ -19,8 +19,8 @@ public interface IArchitectureContext
|
|||||||
/// 获取指定类型的服务实例
|
/// 获取指定类型的服务实例
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <typeparam name="TService">服务类型</typeparam>
|
/// <typeparam name="TService">服务类型</typeparam>
|
||||||
/// <returns>服务实例,如果不存在则返回null</returns>
|
/// <returns>服务实例,如果不存在则抛出异常</returns>
|
||||||
TService? GetService<TService>() where TService : class;
|
TService GetService<TService>() where TService : class;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 获取指定类型的所有服务实例
|
/// 获取指定类型的所有服务实例
|
||||||
@ -33,8 +33,8 @@ public interface IArchitectureContext
|
|||||||
/// 获取指定类型的系统实例
|
/// 获取指定类型的系统实例
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <typeparam name="TSystem">系统类型,必须继承自ISystem接口</typeparam>
|
/// <typeparam name="TSystem">系统类型,必须继承自ISystem接口</typeparam>
|
||||||
/// <returns>系统实例,如果不存在则返回null</returns>
|
/// <returns>系统实例,如果不存在则抛出异常</returns>
|
||||||
TSystem? GetSystem<TSystem>() where TSystem : class, ISystem;
|
TSystem GetSystem<TSystem>() where TSystem : class, ISystem;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 获取指定类型的所有系统实例
|
/// 获取指定类型的所有系统实例
|
||||||
@ -47,8 +47,8 @@ public interface IArchitectureContext
|
|||||||
/// 获取指定类型的模型实例
|
/// 获取指定类型的模型实例
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <typeparam name="TModel">模型类型,必须继承自IModel接口</typeparam>
|
/// <typeparam name="TModel">模型类型,必须继承自IModel接口</typeparam>
|
||||||
/// <returns>模型实例,如果不存在则返回null</returns>
|
/// <returns>模型实例,如果不存在则抛出异常</returns>
|
||||||
TModel? GetModel<TModel>() where TModel : class, IModel;
|
TModel GetModel<TModel>() where TModel : class, IModel;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 获取指定类型的所有模型实例
|
/// 获取指定类型的所有模型实例
|
||||||
@ -61,8 +61,8 @@ public interface IArchitectureContext
|
|||||||
/// 获取指定类型的工具类实例
|
/// 获取指定类型的工具类实例
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <typeparam name="TUtility">工具类类型,必须继承自IUtility接口</typeparam>
|
/// <typeparam name="TUtility">工具类类型,必须继承自IUtility接口</typeparam>
|
||||||
/// <returns>工具类实例,如果不存在则返回null</returns>
|
/// <returns>工具类实例,如果不存在则抛出异常</returns>
|
||||||
TUtility? GetUtility<TUtility>() where TUtility : class, IUtility;
|
TUtility GetUtility<TUtility>() where TUtility : class, IUtility;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 获取指定类型的所有工具类实例
|
/// 获取指定类型的所有工具类实例
|
||||||
@ -71,6 +71,38 @@ public interface IArchitectureContext
|
|||||||
/// <returns>所有符合条件的工具类实例列表</returns>
|
/// <returns>所有符合条件的工具类实例列表</returns>
|
||||||
IReadOnlyList<TUtility> GetUtilities<TUtility>() where TUtility : class, IUtility;
|
IReadOnlyList<TUtility> GetUtilities<TUtility>() where TUtility : class, IUtility;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取指定类型的所有服务实例,并按优先级排序
|
||||||
|
/// 实现 IPrioritized 接口的服务将按优先级排序(数值越小优先级越高)
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="TService">服务类型</typeparam>
|
||||||
|
/// <returns>按优先级排序后的服务实例列表</returns>
|
||||||
|
IReadOnlyList<TService> GetServicesByPriority<TService>() where TService : class;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取指定类型的所有系统实例,并按优先级排序
|
||||||
|
/// 实现 IPrioritized 接口的系统将按优先级排序(数值越小优先级越高)
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="TSystem">系统类型,必须继承自ISystem接口</typeparam>
|
||||||
|
/// <returns>按优先级排序后的系统实例列表</returns>
|
||||||
|
IReadOnlyList<TSystem> GetSystemsByPriority<TSystem>() where TSystem : class, ISystem;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取指定类型的所有模型实例,并按优先级排序
|
||||||
|
/// 实现 IPrioritized 接口的模型将按优先级排序(数值越小优先级越高)
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="TModel">模型类型,必须继承自IModel接口</typeparam>
|
||||||
|
/// <returns>按优先级排序后的模型实例列表</returns>
|
||||||
|
IReadOnlyList<TModel> GetModelsByPriority<TModel>() where TModel : class, IModel;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取指定类型的所有工具类实例,并按优先级排序
|
||||||
|
/// 实现 IPrioritized 接口的工具将按优先级排序(数值越小优先级越高)
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="TUtility">工具类类型,必须继承自IUtility接口</typeparam>
|
||||||
|
/// <returns>按优先级排序后的工具类实例列表</returns>
|
||||||
|
IReadOnlyList<TUtility> GetUtilitiesByPriority<TUtility>() where TUtility : class, IUtility;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 发送一个命令
|
/// 发送一个命令
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -83,7 +115,7 @@ public interface IArchitectureContext
|
|||||||
/// <typeparam name="TResult">命令执行结果类型</typeparam>
|
/// <typeparam name="TResult">命令执行结果类型</typeparam>
|
||||||
/// <param name="command">要发送的命令</param>
|
/// <param name="command">要发送的命令</param>
|
||||||
/// <returns>命令执行结果</returns>
|
/// <returns>命令执行结果</returns>
|
||||||
TResult SendCommand<TResult>(command.ICommand<TResult> command);
|
TResult SendCommand<TResult>(Command.ICommand<TResult> command);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// [Mediator] 发送命令的同步版本(不推荐,仅用于兼容性)
|
/// [Mediator] 发送命令的同步版本(不推荐,仅用于兼容性)
|
||||||
@ -126,7 +158,7 @@ public interface IArchitectureContext
|
|||||||
/// <typeparam name="TResult">查询结果类型</typeparam>
|
/// <typeparam name="TResult">查询结果类型</typeparam>
|
||||||
/// <param name="query">要发送的查询</param>
|
/// <param name="query">要发送的查询</param>
|
||||||
/// <returns>查询结果</returns>
|
/// <returns>查询结果</returns>
|
||||||
TResult SendQuery<TResult>(query.IQuery<TResult> query);
|
TResult SendQuery<TResult>(Query.IQuery<TResult> query);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// [Mediator] 发送查询的同步版本(不推荐,仅用于兼容性)
|
/// [Mediator] 发送查询的同步版本(不推荐,仅用于兼容性)
|
||||||
@ -1,4 +1,4 @@
|
|||||||
namespace GFramework.Core.Abstractions.architecture;
|
namespace GFramework.Core.Abstractions.Architectures;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 架构上下文提供者接口,用于解耦上下文获取逻辑
|
/// 架构上下文提供者接口,用于解耦上下文获取逻辑
|
||||||
@ -1,6 +1,6 @@
|
|||||||
using GFramework.Core.Abstractions.enums;
|
using GFramework.Core.Abstractions.Enums;
|
||||||
|
|
||||||
namespace GFramework.Core.Abstractions.architecture;
|
namespace GFramework.Core.Abstractions.Architectures;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 架构生命周期钩子接口,用于在架构的不同生命周期阶段执行自定义逻辑。
|
/// 架构生命周期钩子接口,用于在架构的不同生命周期阶段执行自定义逻辑。
|
||||||
@ -1,4 +1,4 @@
|
|||||||
namespace GFramework.Core.Abstractions.architecture;
|
namespace GFramework.Core.Abstractions.Architectures;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 架构模块接口,继承自架构生命周期接口。
|
/// 架构模块接口,继承自架构生命周期接口。
|
||||||
@ -1,6 +1,6 @@
|
|||||||
using GFramework.Core.Abstractions.enums;
|
using GFramework.Core.Abstractions.Enums;
|
||||||
|
|
||||||
namespace GFramework.Core.Abstractions.architecture;
|
namespace GFramework.Core.Abstractions.Architectures;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 架构阶段监听器接口,用于监听和响应架构生命周期中的不同阶段变化。
|
/// 架构阶段监听器接口,用于监听和响应架构生命周期中的不同阶段变化。
|
||||||
@ -1,10 +1,10 @@
|
|||||||
using GFramework.Core.Abstractions.command;
|
using GFramework.Core.Abstractions.Command;
|
||||||
using GFramework.Core.Abstractions.events;
|
using GFramework.Core.Abstractions.Events;
|
||||||
using GFramework.Core.Abstractions.ioc;
|
using GFramework.Core.Abstractions.Ioc;
|
||||||
using GFramework.Core.Abstractions.query;
|
using GFramework.Core.Abstractions.Query;
|
||||||
using GFramework.Core.Abstractions.rule;
|
using GFramework.Core.Abstractions.Rule;
|
||||||
|
|
||||||
namespace GFramework.Core.Abstractions.architecture;
|
namespace GFramework.Core.Abstractions.Architectures;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 架构服务接口,定义了框架核心架构所需的服务组件
|
/// 架构服务接口,定义了框架核心架构所需的服务组件
|
||||||
@ -1,7 +1,7 @@
|
|||||||
using GFramework.Core.Abstractions.ioc;
|
using GFramework.Core.Abstractions.Ioc;
|
||||||
using GFramework.Core.Abstractions.lifecycle;
|
using GFramework.Core.Abstractions.Lifecycle;
|
||||||
|
|
||||||
namespace GFramework.Core.Abstractions.architecture;
|
namespace GFramework.Core.Abstractions.Architectures;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 服务模块接口,定义了服务模块的基本契约。
|
/// 服务模块接口,定义了服务模块的基本契约。
|
||||||
@ -1,7 +1,6 @@
|
|||||||
using GFramework.Core.Abstractions.ioc;
|
using GFramework.Core.Abstractions.Ioc;
|
||||||
using GFramework.Core.Abstractions.properties;
|
|
||||||
|
|
||||||
namespace GFramework.Core.Abstractions.architecture;
|
namespace GFramework.Core.Abstractions.Architectures;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 服务模块管理器接口,用于管理架构中的服务模块。
|
/// 服务模块管理器接口,用于管理架构中的服务模块。
|
||||||
@ -18,8 +17,7 @@ public interface IServiceModuleManager
|
|||||||
/// 注册内置的服务模块。
|
/// 注册内置的服务模块。
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="container">IoC容器实例,用于解析依赖。</param>
|
/// <param name="container">IoC容器实例,用于解析依赖。</param>
|
||||||
/// <param name="properties">架构属性配置,用于模块初始化。</param>
|
void RegisterBuiltInModules(IIocContainer container);
|
||||||
void RegisterBuiltInModules(IIocContainer container, ArchitectureProperties properties);
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 获取所有已注册的服务模块。
|
/// 获取所有已注册的服务模块。
|
||||||
@ -11,7 +11,7 @@
|
|||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
namespace GFramework.Core.Abstractions.bases;
|
namespace GFramework.Core.Abstractions.Bases;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 定义具有键值访问能力的接口契约
|
/// 定义具有键值访问能力的接口契约
|
||||||
@ -1,4 +1,4 @@
|
|||||||
namespace GFramework.Core.Abstractions.bases;
|
namespace GFramework.Core.Abstractions.Bases;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 表示键值对的接口,定义了通用的键值对数据结构契约
|
/// 表示键值对的接口,定义了通用的键值对数据结构契约
|
||||||
17
GFramework.Core.Abstractions/Bases/IPrioritized.cs
Normal file
17
GFramework.Core.Abstractions/Bases/IPrioritized.cs
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
namespace GFramework.Core.Abstractions.Bases;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 定义具有优先级的对象接口。
|
||||||
|
/// 数值越小优先级越高,越先执行。
|
||||||
|
/// 用于控制服务、系统等组件的执行顺序。
|
||||||
|
/// </summary>
|
||||||
|
public interface IPrioritized
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 获取优先级值。
|
||||||
|
/// 数值越小优先级越高。
|
||||||
|
/// 默认优先级为 0。
|
||||||
|
/// 建议范围:-1000 到 1000。
|
||||||
|
/// </summary>
|
||||||
|
int Priority { get; }
|
||||||
|
}
|
||||||
71
GFramework.Core.Abstractions/Bases/PriorityGroup.cs
Normal file
71
GFramework.Core.Abstractions/Bases/PriorityGroup.cs
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
namespace GFramework.Core.Abstractions.Bases;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 预定义的优先级分组常量
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// 提供标准化的优先级值,用于统一管理系统、服务等组件的执行顺序。
|
||||||
|
/// 优先级值越小,优先级越高(负数表示高优先级)。
|
||||||
|
/// </remarks>
|
||||||
|
public static class PriorityGroup
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 关键优先级 - 最高优先级,用于核心系统和基础设施
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// 适用场景:
|
||||||
|
/// - 日志系统
|
||||||
|
/// - 配置管理
|
||||||
|
/// - IoC 容器初始化
|
||||||
|
/// - 架构核心组件
|
||||||
|
/// </remarks>
|
||||||
|
public const int Critical = -100;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 高优先级 - 用于重要但非核心的系统
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// 适用场景:
|
||||||
|
/// - 事件总线
|
||||||
|
/// - 资源管理器
|
||||||
|
/// - 输入系统
|
||||||
|
/// - 网络管理器
|
||||||
|
/// </remarks>
|
||||||
|
public const int High = -50;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 普通优先级 - 默认优先级
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// 适用场景:
|
||||||
|
/// - 游戏逻辑系统
|
||||||
|
/// - UI 系统
|
||||||
|
/// - 音频系统
|
||||||
|
/// - 大部分业务逻辑
|
||||||
|
/// </remarks>
|
||||||
|
public const int Normal = 0;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 低优先级 - 用于非关键系统
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// 适用场景:
|
||||||
|
/// - 统计系统
|
||||||
|
/// - 调试工具
|
||||||
|
/// - 性能监控
|
||||||
|
/// - 辅助功能
|
||||||
|
/// </remarks>
|
||||||
|
public const int Low = 50;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 延迟优先级 - 最低优先级,用于可延迟执行的系统
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// 适用场景:
|
||||||
|
/// - 分析和遥测
|
||||||
|
/// - 后台数据同步
|
||||||
|
/// - 缓存清理
|
||||||
|
/// - 非紧急任务
|
||||||
|
/// </remarks>
|
||||||
|
public const int Deferred = 100;
|
||||||
|
}
|
||||||
@ -1,6 +1,6 @@
|
|||||||
using GFramework.Core.Abstractions.rule;
|
using GFramework.Core.Abstractions.Rule;
|
||||||
|
|
||||||
namespace GFramework.Core.Abstractions.command;
|
namespace GFramework.Core.Abstractions.Command;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 表示一个异步命令接口,该命令不返回结果
|
/// 表示一个异步命令接口,该命令不返回结果
|
||||||
@ -1,6 +1,6 @@
|
|||||||
using GFramework.Core.Abstractions.rule;
|
using GFramework.Core.Abstractions.Rule;
|
||||||
|
|
||||||
namespace GFramework.Core.Abstractions.command;
|
namespace GFramework.Core.Abstractions.Command;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 命令接口,定义了无返回值命令的基本契约
|
/// 命令接口,定义了无返回值命令的基本契约
|
||||||
@ -1,4 +1,4 @@
|
|||||||
namespace GFramework.Core.Abstractions.command;
|
namespace GFramework.Core.Abstractions.Command;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 定义命令执行器接口,提供同步和异步方式发送并执行命令的方法。
|
/// 定义命令执行器接口,提供同步和异步方式发送并执行命令的方法。
|
||||||
@ -0,0 +1,49 @@
|
|||||||
|
// Copyright (c) 2025 GeWuYou
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
using GFramework.Core.Abstractions.Utility;
|
||||||
|
|
||||||
|
namespace GFramework.Core.Abstractions.Concurrency;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 异步键锁管理器接口,提供基于键的细粒度锁机制
|
||||||
|
/// </summary>
|
||||||
|
public interface IAsyncKeyLockManager : IUtility, IDisposable
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 异步获取指定键的锁(推荐使用)
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="key">锁键</param>
|
||||||
|
/// <param name="cancellationToken">取消令牌</param>
|
||||||
|
/// <returns>锁句柄,使用 await using 自动释放</returns>
|
||||||
|
ValueTask<IAsyncLockHandle> AcquireLockAsync(string key, CancellationToken cancellationToken = default);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 同步获取指定键的锁(兼容性方法)
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="key">锁键</param>
|
||||||
|
/// <returns>锁句柄,使用 using 自动释放</returns>
|
||||||
|
IAsyncLockHandle AcquireLock(string key);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取锁管理器的统计信息
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>统计信息快照</returns>
|
||||||
|
LockStatistics GetStatistics();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取当前活跃的锁信息(用于调试)
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>键到锁信息的只读字典</returns>
|
||||||
|
IReadOnlyDictionary<string, LockInfo> GetActiveLocks();
|
||||||
|
}
|
||||||
30
GFramework.Core.Abstractions/Concurrency/IAsyncLockHandle.cs
Normal file
30
GFramework.Core.Abstractions/Concurrency/IAsyncLockHandle.cs
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
// Copyright (c) 2025 GeWuYou
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
namespace GFramework.Core.Abstractions.Concurrency;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 异步锁句柄接口,支持 await using 语法
|
||||||
|
/// </summary>
|
||||||
|
public interface IAsyncLockHandle : IAsyncDisposable, IDisposable
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 锁的键
|
||||||
|
/// </summary>
|
||||||
|
string Key { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 锁获取时的时间戳(Environment.TickCount64)
|
||||||
|
/// </summary>
|
||||||
|
long AcquiredTicks { get; }
|
||||||
|
}
|
||||||
43
GFramework.Core.Abstractions/Concurrency/LockInfo.cs
Normal file
43
GFramework.Core.Abstractions/Concurrency/LockInfo.cs
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
// Copyright (c) 2025 GeWuYou
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
namespace GFramework.Core.Abstractions.Concurrency;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 锁信息(用于调试)
|
||||||
|
/// </summary>
|
||||||
|
public readonly struct LockInfo
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 锁的键。
|
||||||
|
/// </summary>
|
||||||
|
public string Key { get; init; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 当前引用计数。
|
||||||
|
/// </summary>
|
||||||
|
public int ReferenceCount { get; init; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 最后访问时间戳(Environment.TickCount64)。
|
||||||
|
/// </summary>
|
||||||
|
public long LastAccessTicks { get; init; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 等待队列长度(近似值)。
|
||||||
|
/// 注意:这是一个基于 SemaphoreSlim.CurrentCount 的近似指示器,
|
||||||
|
/// 当 CurrentCount == 0 时表示锁被持有且可能有等待者,返回 1;
|
||||||
|
/// 否则返回 0。这不是精确的等待者数量,仅用于调试参考。
|
||||||
|
/// </summary>
|
||||||
|
public int WaitingCount { get; init; }
|
||||||
|
}
|
||||||
43
GFramework.Core.Abstractions/Concurrency/LockStatistics.cs
Normal file
43
GFramework.Core.Abstractions/Concurrency/LockStatistics.cs
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
// Copyright (c) 2025 GeWuYou
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
|
namespace GFramework.Core.Abstractions.Concurrency;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 锁统计信息
|
||||||
|
/// </summary>
|
||||||
|
[StructLayout(LayoutKind.Auto)]
|
||||||
|
public readonly struct LockStatistics
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 当前活跃的锁数量
|
||||||
|
/// </summary>
|
||||||
|
public int ActiveLockCount { get; init; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 累计获取锁的次数
|
||||||
|
/// </summary>
|
||||||
|
public int TotalAcquired { get; init; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 累计释放锁的次数
|
||||||
|
/// </summary>
|
||||||
|
public int TotalReleased { get; init; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 累计清理的锁数量
|
||||||
|
/// </summary>
|
||||||
|
public int TotalCleaned { get; init; }
|
||||||
|
}
|
||||||
@ -1,7 +1,7 @@
|
|||||||
using GFramework.Core.Abstractions.events;
|
using GFramework.Core.Abstractions.Events;
|
||||||
using GFramework.Core.Abstractions.utility;
|
using GFramework.Core.Abstractions.Utility;
|
||||||
|
|
||||||
namespace GFramework.Core.Abstractions.configuration;
|
namespace GFramework.Core.Abstractions.Configuration;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 配置管理器接口,提供类型安全的配置存储和访问
|
/// 配置管理器接口,提供类型安全的配置存储和访问
|
||||||
38
GFramework.Core.Abstractions/Controller/IController.cs
Normal file
38
GFramework.Core.Abstractions/Controller/IController.cs
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
namespace GFramework.Core.Abstractions.Controller;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 控制器标记接口,用于标识控制器组件
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// <para>
|
||||||
|
/// IController 是一个标记接口(Marker Interface),不包含任何方法或属性。
|
||||||
|
/// 它的作用是标识一个类是控制器,用于协调 Model、System 和 UI 之间的交互。
|
||||||
|
/// </para>
|
||||||
|
/// <para>
|
||||||
|
/// 架构访问 :控制器通常需要访问架构上下文。使用 [ContextAware] 特性
|
||||||
|
/// 自动生成上下文访问能力:
|
||||||
|
/// </para>
|
||||||
|
/// <code>
|
||||||
|
/// using GFramework.SourceGenerators.Abstractions.Rule;
|
||||||
|
///
|
||||||
|
/// [ContextAware]
|
||||||
|
/// public partial class PlayerController : IController
|
||||||
|
/// {
|
||||||
|
/// public void Initialize()
|
||||||
|
/// {
|
||||||
|
/// // [ContextAware] 实现 IContextAware 接口,可使用扩展方法
|
||||||
|
/// var playerModel = this.GetModel<PlayerModel>();
|
||||||
|
/// var gameSystem = this.GetSystem<GameSystem>();
|
||||||
|
/// }
|
||||||
|
/// }
|
||||||
|
/// </code>
|
||||||
|
/// <para>
|
||||||
|
/// 注意:
|
||||||
|
/// </para>
|
||||||
|
/// <list type="bullet">
|
||||||
|
/// <item>必须添加 partial 关键字</item>
|
||||||
|
/// <item>[ContextAware] 特性会自动实现 IContextAware 接口</item>
|
||||||
|
/// <item>可使用 this.GetModel()、this.GetSystem() 等扩展方法访问架构</item>
|
||||||
|
/// </list>
|
||||||
|
/// </remarks>
|
||||||
|
public interface IController;
|
||||||
33
GFramework.Core.Abstractions/Coroutine/CoroutinePriority.cs
Normal file
33
GFramework.Core.Abstractions/Coroutine/CoroutinePriority.cs
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
namespace GFramework.Core.Abstractions.Coroutine;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 协程优先级枚举
|
||||||
|
/// 定义协程的执行优先级,高优先级的协程会优先执行
|
||||||
|
/// </summary>
|
||||||
|
public enum CoroutinePriority
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 最低优先级
|
||||||
|
/// </summary>
|
||||||
|
Lowest = 0,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 低优先级
|
||||||
|
/// </summary>
|
||||||
|
Low = 1,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 普通优先级(默认)
|
||||||
|
/// </summary>
|
||||||
|
Normal = 2,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 高优先级
|
||||||
|
/// </summary>
|
||||||
|
High = 3,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 最高优先级
|
||||||
|
/// </summary>
|
||||||
|
Highest = 4
|
||||||
|
}
|
||||||
@ -1,4 +1,4 @@
|
|||||||
namespace GFramework.Core.Abstractions.coroutine;
|
namespace GFramework.Core.Abstractions.Coroutine;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 表示协程的执行状态枚举
|
/// 表示协程的执行状态枚举
|
||||||
@ -0,0 +1,68 @@
|
|||||||
|
namespace GFramework.Core.Abstractions.Coroutine;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 协程统计信息接口
|
||||||
|
/// 提供协程执行的性能统计数据
|
||||||
|
/// </summary>
|
||||||
|
public interface ICoroutineStatistics
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 获取总协程启动数量
|
||||||
|
/// </summary>
|
||||||
|
long TotalStarted { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取总协程完成数量
|
||||||
|
/// </summary>
|
||||||
|
long TotalCompleted { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取总协程失败数量
|
||||||
|
/// </summary>
|
||||||
|
long TotalFailed { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取当前活跃协程数量
|
||||||
|
/// </summary>
|
||||||
|
int ActiveCount { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取当前暂停协程数量
|
||||||
|
/// </summary>
|
||||||
|
int PausedCount { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取协程平均执行时间(毫秒)
|
||||||
|
/// </summary>
|
||||||
|
double AverageExecutionTimeMs { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取协程最大执行时间(毫秒)
|
||||||
|
/// </summary>
|
||||||
|
double MaxExecutionTimeMs { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取按优先级分组的协程数量
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="priority">协程优先级</param>
|
||||||
|
/// <returns>指定优先级的协程数量</returns>
|
||||||
|
int GetCountByPriority(CoroutinePriority priority);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取按标签分组的协程数量
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="tag">协程标签</param>
|
||||||
|
/// <returns>指定标签的协程数量</returns>
|
||||||
|
int GetCountByTag(string tag);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 重置统计数据
|
||||||
|
/// </summary>
|
||||||
|
void Reset();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 生成统计报告
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>格式化的统计报告字符串</returns>
|
||||||
|
string GenerateReport();
|
||||||
|
}
|
||||||
@ -1,4 +1,4 @@
|
|||||||
namespace GFramework.Core.Abstractions.coroutine;
|
namespace GFramework.Core.Abstractions.Coroutine;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 时间源接口,提供当前时间、时间增量以及更新功能
|
/// 时间源接口,提供当前时间、时间增量以及更新功能
|
||||||
@ -1,4 +1,4 @@
|
|||||||
namespace GFramework.Core.Abstractions.coroutine;
|
namespace GFramework.Core.Abstractions.Coroutine;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 定义一个可等待指令的接口,用于协程系统中的异步操作控制
|
/// 定义一个可等待指令的接口,用于协程系统中的异步操作控制
|
||||||
@ -1,4 +1,4 @@
|
|||||||
namespace GFramework.Core.Abstractions.cqrs.command;
|
namespace GFramework.Core.Abstractions.Cqrs.Command;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 命令输入接口,定义命令模式中输入数据的契约
|
/// 命令输入接口,定义命令模式中输入数据的契约
|
||||||
@ -11,7 +11,7 @@
|
|||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
namespace GFramework.Core.Abstractions.cqrs;
|
namespace GFramework.Core.Abstractions.Cqrs;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 表示输入数据的标记接口。
|
/// 表示输入数据的标记接口。
|
||||||
@ -11,7 +11,7 @@
|
|||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
namespace GFramework.Core.Abstractions.cqrs.notification;
|
namespace GFramework.Core.Abstractions.Cqrs.Notification;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 表示通知输入数据的标记接口。
|
/// 表示通知输入数据的标记接口。
|
||||||
@ -1,4 +1,4 @@
|
|||||||
namespace GFramework.Core.Abstractions.cqrs.query;
|
namespace GFramework.Core.Abstractions.Cqrs.Query;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 查询输入接口,定义了查询操作的输入规范
|
/// 查询输入接口,定义了查询操作的输入规范
|
||||||
@ -11,7 +11,7 @@
|
|||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
namespace GFramework.Core.Abstractions.cqrs.request;
|
namespace GFramework.Core.Abstractions.Cqrs.Request;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 表示请求输入数据的标记接口。
|
/// 表示请求输入数据的标记接口。
|
||||||
@ -11,7 +11,7 @@
|
|||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
namespace GFramework.Core.Abstractions.data;
|
namespace GFramework.Core.Abstractions.Data;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 定义从指定类型数据源加载数据的接口
|
/// 定义从指定类型数据源加载数据的接口
|
||||||
@ -1,4 +1,4 @@
|
|||||||
namespace GFramework.Core.Abstractions.enums;
|
namespace GFramework.Core.Abstractions.Enums;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 架构阶段枚举,定义了系统架构初始化和运行过程中的各个关键阶段
|
/// 架构阶段枚举,定义了系统架构初始化和运行过程中的各个关键阶段
|
||||||
@ -1,4 +1,4 @@
|
|||||||
namespace GFramework.Core.Abstractions.environment;
|
namespace GFramework.Core.Abstractions.Environment;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 定义环境接口,提供应用程序运行环境的相关信息
|
/// 定义环境接口,提供应用程序运行环境的相关信息
|
||||||
@ -1,4 +1,4 @@
|
|||||||
namespace GFramework.Core.Abstractions.events;
|
namespace GFramework.Core.Abstractions.Events;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 事件上下文,包装事件数据并提供控制方法
|
/// 事件上下文,包装事件数据并提供控制方法
|
||||||
@ -1,4 +1,4 @@
|
|||||||
namespace GFramework.Core.Abstractions.events;
|
namespace GFramework.Core.Abstractions.Events;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 事件传播模式
|
/// 事件传播模式
|
||||||
@ -1,4 +1,4 @@
|
|||||||
namespace GFramework.Core.Abstractions.events;
|
namespace GFramework.Core.Abstractions.Events;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 事件接口,定义了事件注册的基本功能
|
/// 事件接口,定义了事件注册的基本功能
|
||||||
@ -1,4 +1,4 @@
|
|||||||
namespace GFramework.Core.Abstractions.events;
|
namespace GFramework.Core.Abstractions.Events;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 事件总线接口,提供事件的发送、注册和注销功能
|
/// 事件总线接口,提供事件的发送、注册和注销功能
|
||||||
16
GFramework.Core.Abstractions/Events/IEventFilter.cs
Normal file
16
GFramework.Core.Abstractions/Events/IEventFilter.cs
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
namespace GFramework.Core.Abstractions.Events;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 事件过滤器接口
|
||||||
|
/// 用于在事件触发前进行条件判断,决定是否允许事件传递给监听器
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T">事件类型</typeparam>
|
||||||
|
public interface IEventFilter<in T>
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 判断事件是否应该被过滤(阻止传递)
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="eventData">事件数据</param>
|
||||||
|
/// <returns>如果返回 true,则事件被过滤(不传递给监听器);如果返回 false,则允许传递</returns>
|
||||||
|
bool ShouldFilter(T eventData);
|
||||||
|
}
|
||||||
58
GFramework.Core.Abstractions/Events/IEventStatistics.cs
Normal file
58
GFramework.Core.Abstractions/Events/IEventStatistics.cs
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
namespace GFramework.Core.Abstractions.Events;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 事件统计信息接口
|
||||||
|
/// 提供事件系统的性能统计数据
|
||||||
|
/// </summary>
|
||||||
|
public interface IEventStatistics
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 获取总事件发布数量
|
||||||
|
/// </summary>
|
||||||
|
long TotalPublished { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取总事件处理数量(监听器调用次数)
|
||||||
|
/// </summary>
|
||||||
|
long TotalHandled { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取总事件处理失败数量
|
||||||
|
/// </summary>
|
||||||
|
long TotalFailed { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取当前活跃的事件类型数量
|
||||||
|
/// </summary>
|
||||||
|
int ActiveEventTypes { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取当前活跃的监听器总数
|
||||||
|
/// </summary>
|
||||||
|
int ActiveListeners { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取指定事件类型的发布次数
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="eventType">事件类型名称</param>
|
||||||
|
/// <returns>发布次数</returns>
|
||||||
|
long GetPublishCount(string eventType);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取指定事件类型的监听器数量
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="eventType">事件类型名称</param>
|
||||||
|
/// <returns>监听器数量</returns>
|
||||||
|
int GetListenerCount(string eventType);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 重置统计数据
|
||||||
|
/// </summary>
|
||||||
|
void Reset();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 生成统计报告
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>格式化的统计报告字符串</returns>
|
||||||
|
string GenerateReport();
|
||||||
|
}
|
||||||
@ -1,4 +1,4 @@
|
|||||||
namespace GFramework.Core.Abstractions.events;
|
namespace GFramework.Core.Abstractions.Events;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 提供注销功能的接口
|
/// 提供注销功能的接口
|
||||||
@ -1,4 +1,4 @@
|
|||||||
namespace GFramework.Core.Abstractions.events;
|
namespace GFramework.Core.Abstractions.Events;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 提供统一注销功能的接口,用于管理需要注销的对象列表
|
/// 提供统一注销功能的接口,用于管理需要注销的对象列表
|
||||||
@ -17,11 +17,11 @@
|
|||||||
<Using Include="GFramework.Core.Abstractions"/>
|
<Using Include="GFramework.Core.Abstractions"/>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Update="Meziantou.Analyzer" Version="3.0.17">
|
<PackageReference Update="Meziantou.Analyzer" Version="3.0.25">
|
||||||
<PrivateAssets>all</PrivateAssets>
|
<PrivateAssets>all</PrivateAssets>
|
||||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
|
||||||
</PackageReference>
|
</PackageReference>
|
||||||
<PackageReference Update="Meziantou.Polyfill" Version="1.0.101">
|
<PackageReference Update="Meziantou.Polyfill" Version="1.0.104">
|
||||||
<PrivateAssets>all</PrivateAssets>
|
<PrivateAssets>all</PrivateAssets>
|
||||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
|
||||||
</PackageReference>
|
</PackageReference>
|
||||||
|
|||||||
@ -1,18 +1,20 @@
|
|||||||
// IsExternalInit.cs
|
// IsExternalInit.cs
|
||||||
// This type is required to support init-only setters and record types
|
// This type is required to support init-only setters and record types
|
||||||
// when targeting netstandard2.0 or older frameworks.
|
// when targeting netstandard2.0 or older frameworks.
|
||||||
|
|
||||||
#if !NET5_0_OR_GREATER
|
#if !NET5_0_OR_GREATER
|
||||||
using System.ComponentModel;
|
using System.ComponentModel;
|
||||||
|
|
||||||
namespace System.Runtime.CompilerServices;
|
// ReSharper disable CheckNamespace
|
||||||
|
|
||||||
/// <summary>
|
namespace System.Runtime.CompilerServices;
|
||||||
/// 提供一个占位符类型,用于支持 C# 9.0 的 init 访问器功能。
|
|
||||||
/// 该类型在 .NET 5.0 及更高版本中已内置,因此仅在较低版本的 .NET 中定义。
|
/// <summary>
|
||||||
/// </summary>
|
/// 提供一个占位符类型,用于支持 C# 9.0 的 init 访问器功能。
|
||||||
[EditorBrowsable(EditorBrowsableState.Never)]
|
/// 该类型在 .NET 5.0 及更高版本中已内置,因此仅在较低版本的 .NET 中定义。
|
||||||
internal static class IsExternalInit
|
/// </summary>
|
||||||
{
|
[EditorBrowsable(EditorBrowsableState.Never)]
|
||||||
}
|
internal static class IsExternalInit
|
||||||
|
{
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
@ -1,8 +1,8 @@
|
|||||||
using GFramework.Core.Abstractions.rule;
|
using GFramework.Core.Abstractions.Rule;
|
||||||
using GFramework.Core.Abstractions.system;
|
using GFramework.Core.Abstractions.Systems;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
|
||||||
namespace GFramework.Core.Abstractions.ioc;
|
namespace GFramework.Core.Abstractions.Ioc;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 依赖注入容器接口,定义了服务注册、解析和管理的基本操作
|
/// 依赖注入容器接口,定义了服务注册、解析和管理的基本操作
|
||||||
@ -165,6 +165,24 @@ public interface IIocContainer : IContextAware
|
|||||||
/// <returns>按指定方式排序后的实例列表</returns>
|
/// <returns>按指定方式排序后的实例列表</returns>
|
||||||
IReadOnlyList<T> GetAllSorted<T>(Comparison<T> comparison) where T : class;
|
IReadOnlyList<T> GetAllSorted<T>(Comparison<T> comparison) where T : class;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取指定类型的所有实例,并按优先级排序
|
||||||
|
/// 实现 IPrioritized 接口的服务将按优先级排序(数值越小优先级越高)
|
||||||
|
/// 未实现 IPrioritized 的服务将使用默认优先级 0
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T">期望获取的实例类型</typeparam>
|
||||||
|
/// <returns>按优先级排序后的实例列表</returns>
|
||||||
|
IReadOnlyList<T> GetAllByPriority<T>() where T : class;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取指定类型的所有实例,并按优先级排序
|
||||||
|
/// 实现 IPrioritized 接口的服务将按优先级排序(数值越小优先级越高)
|
||||||
|
/// 未实现 IPrioritized 的服务将使用默认优先级 0
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="type">期望获取的实例类型</param>
|
||||||
|
/// <returns>按优先级排序后的实例列表</returns>
|
||||||
|
IReadOnlyList<object> GetAllByPriority(Type type);
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Utility Methods
|
#region Utility Methods
|
||||||
@ -1,4 +1,4 @@
|
|||||||
namespace GFramework.Core.Abstractions.lifecycle;
|
namespace GFramework.Core.Abstractions.Lifecycle;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 定义异步销毁接口,用于需要异步清理资源的组件
|
/// 定义异步销毁接口,用于需要异步清理资源的组件
|
||||||
@ -1,4 +1,4 @@
|
|||||||
namespace GFramework.Core.Abstractions.lifecycle;
|
namespace GFramework.Core.Abstractions.Lifecycle;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 定义异步初始化接口,用于需要异步初始化的组件或服务
|
/// 定义异步初始化接口,用于需要异步初始化的组件或服务
|
||||||
@ -1,4 +1,4 @@
|
|||||||
namespace GFramework.Core.Abstractions.lifecycle;
|
namespace GFramework.Core.Abstractions.Lifecycle;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 定义异步生命周期接口,组合了异步初始化和异步销毁
|
/// 定义异步生命周期接口,组合了异步初始化和异步销毁
|
||||||
@ -1,4 +1,4 @@
|
|||||||
namespace GFramework.Core.Abstractions.lifecycle;
|
namespace GFramework.Core.Abstractions.Lifecycle;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 可销毁接口,为需要资源清理的组件提供标准销毁能力
|
/// 可销毁接口,为需要资源清理的组件提供标准销毁能力
|
||||||
@ -1,4 +1,4 @@
|
|||||||
namespace GFramework.Core.Abstractions.lifecycle;
|
namespace GFramework.Core.Abstractions.Lifecycle;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 可初始化接口,为需要初始化的组件提供标准初始化能力
|
/// 可初始化接口,为需要初始化的组件提供标准初始化能力
|
||||||
@ -1,4 +1,4 @@
|
|||||||
namespace GFramework.Core.Abstractions.lifecycle;
|
namespace GFramework.Core.Abstractions.Lifecycle;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 完整生命周期接口,组合了初始化和销毁能力
|
/// 完整生命周期接口,组合了初始化和销毁能力
|
||||||
@ -0,0 +1,22 @@
|
|||||||
|
namespace GFramework.Core.Abstractions.Localization;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 本地化格式化器接口
|
||||||
|
/// </summary>
|
||||||
|
public interface ILocalizationFormatter
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 格式化器名称
|
||||||
|
/// </summary>
|
||||||
|
string Name { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 尝试格式化值
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="format">格式字符串</param>
|
||||||
|
/// <param name="value">要格式化的值</param>
|
||||||
|
/// <param name="provider">格式提供者</param>
|
||||||
|
/// <param name="result">格式化结果</param>
|
||||||
|
/// <returns>是否成功格式化</returns>
|
||||||
|
bool TryFormat(string format, object value, IFormatProvider? provider, out string result);
|
||||||
|
}
|
||||||
@ -0,0 +1,89 @@
|
|||||||
|
using System.Globalization;
|
||||||
|
using GFramework.Core.Abstractions.Systems;
|
||||||
|
|
||||||
|
namespace GFramework.Core.Abstractions.Localization;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 本地化管理器接口
|
||||||
|
/// </summary>
|
||||||
|
public interface ILocalizationManager : ISystem
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 当前语言代码
|
||||||
|
/// </summary>
|
||||||
|
string CurrentLanguage { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 当前文化信息
|
||||||
|
/// </summary>
|
||||||
|
CultureInfo CurrentCulture { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 可用语言列表
|
||||||
|
/// </summary>
|
||||||
|
IReadOnlyList<string> AvailableLanguages { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 设置当前语言
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="languageCode">语言代码</param>
|
||||||
|
void SetLanguage(string languageCode);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取本地化表
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="tableName">表名</param>
|
||||||
|
/// <returns>本地化表</returns>
|
||||||
|
ILocalizationTable GetTable(string tableName);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取本地化文本
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="table">表名</param>
|
||||||
|
/// <param name="key">键名</param>
|
||||||
|
/// <returns>本地化文本</returns>
|
||||||
|
string GetText(string table, string key);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取本地化字符串(支持变量和格式化)
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="table">表名</param>
|
||||||
|
/// <param name="key">键名</param>
|
||||||
|
/// <returns>本地化字符串</returns>
|
||||||
|
ILocalizationString GetString(string table, string key);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 尝试获取本地化文本
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="table">表名</param>
|
||||||
|
/// <param name="key">键名</param>
|
||||||
|
/// <param name="text">输出文本</param>
|
||||||
|
/// <returns>是否成功获取</returns>
|
||||||
|
bool TryGetText(string table, string key, out string text);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 注册格式化器
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="name">格式化器名称</param>
|
||||||
|
/// <param name="formatter">格式化器实例</param>
|
||||||
|
void RegisterFormatter(string name, ILocalizationFormatter formatter);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取格式化器
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="name">格式化器名称</param>
|
||||||
|
/// <returns>格式化器实例,如果不存在则返回 null</returns>
|
||||||
|
ILocalizationFormatter? GetFormatter(string name);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 订阅语言变化事件
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="callback">回调函数</param>
|
||||||
|
void SubscribeToLanguageChange(Action<string> callback);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 取消订阅语言变化事件
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="callback">回调函数</param>
|
||||||
|
void UnsubscribeFromLanguageChange(Action<string> callback);
|
||||||
|
}
|
||||||
@ -0,0 +1,50 @@
|
|||||||
|
namespace GFramework.Core.Abstractions.Localization;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 本地化字符串接口(支持变量和格式化)
|
||||||
|
/// </summary>
|
||||||
|
public interface ILocalizationString
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 表名
|
||||||
|
/// </summary>
|
||||||
|
string Table { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 键名
|
||||||
|
/// </summary>
|
||||||
|
string Key { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 添加变量
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="name">变量名</param>
|
||||||
|
/// <param name="value">变量值</param>
|
||||||
|
/// <returns>当前实例(支持链式调用)</returns>
|
||||||
|
ILocalizationString WithVariable(string name, object value);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 批量添加变量
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="variables">变量数组</param>
|
||||||
|
/// <returns>当前实例(支持链式调用)</returns>
|
||||||
|
ILocalizationString WithVariables(params (string name, object value)[] variables);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 格式化并返回最终文本
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>格式化后的文本</returns>
|
||||||
|
string Format();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取原始文本(不进行格式化)
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>原始文本</returns>
|
||||||
|
string GetRaw();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 检查键是否存在
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>是否存在</returns>
|
||||||
|
bool Exists();
|
||||||
|
}
|
||||||
@ -0,0 +1,48 @@
|
|||||||
|
namespace GFramework.Core.Abstractions.Localization;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 本地化表接口
|
||||||
|
/// </summary>
|
||||||
|
public interface ILocalizationTable
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 表名
|
||||||
|
/// </summary>
|
||||||
|
string Name { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 语言代码
|
||||||
|
/// </summary>
|
||||||
|
string Language { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 回退表(当前表中找不到键时使用)
|
||||||
|
/// </summary>
|
||||||
|
ILocalizationTable? Fallback { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取原始文本(不进行格式化)
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="key">键名</param>
|
||||||
|
/// <returns>原始文本</returns>
|
||||||
|
string GetRawText(string key);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 检查是否包含指定键
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="key">键名</param>
|
||||||
|
/// <returns>是否包含</returns>
|
||||||
|
bool ContainsKey(string key);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取所有键
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>键集合</returns>
|
||||||
|
IEnumerable<string> GetKeys();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 合并覆盖数据
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="overrides">覆盖数据</param>
|
||||||
|
void Merge(IReadOnlyDictionary<string, string> overrides);
|
||||||
|
}
|
||||||
@ -0,0 +1,37 @@
|
|||||||
|
namespace GFramework.Core.Abstractions.Localization;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 本地化配置
|
||||||
|
/// </summary>
|
||||||
|
public class LocalizationConfig
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 默认语言代码
|
||||||
|
/// </summary>
|
||||||
|
public string DefaultLanguage { get; set; } = "eng";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 回退语言代码(当目标语言缺少键时使用)
|
||||||
|
/// </summary>
|
||||||
|
public string FallbackLanguage { get; set; } = "eng";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 本地化文件路径(Godot 资源路径)
|
||||||
|
/// </summary>
|
||||||
|
public string LocalizationPath { get; set; } = "res://localization";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 用户覆盖文件路径(用于热更新和自定义翻译)
|
||||||
|
/// </summary>
|
||||||
|
public string OverridePath { get; set; } = "user://localization_override";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 是否启用热重载(监视覆盖文件变化)
|
||||||
|
/// </summary>
|
||||||
|
public bool EnableHotReload { get; set; } = true;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 是否在加载时验证本地化文件
|
||||||
|
/// </summary>
|
||||||
|
public bool ValidateOnLoad { get; set; } = true;
|
||||||
|
}
|
||||||
@ -0,0 +1,31 @@
|
|||||||
|
namespace GFramework.Core.Abstractions.Localization;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 本地化异常基类
|
||||||
|
/// </summary>
|
||||||
|
public class LocalizationException : Exception
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 初始化本地化异常
|
||||||
|
/// </summary>
|
||||||
|
public LocalizationException()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 初始化本地化异常
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="message">异常消息</param>
|
||||||
|
public LocalizationException(string message) : base(message)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 初始化本地化异常
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="message">异常消息</param>
|
||||||
|
/// <param name="innerException">内部异常</param>
|
||||||
|
public LocalizationException(string message, Exception innerException) : base(message, innerException)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,29 @@
|
|||||||
|
namespace GFramework.Core.Abstractions.Localization;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 本地化键未找到异常
|
||||||
|
/// </summary>
|
||||||
|
public class LocalizationKeyNotFoundException : LocalizationException
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 初始化键未找到异常
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="tableName">表名</param>
|
||||||
|
/// <param name="key">键名</param>
|
||||||
|
public LocalizationKeyNotFoundException(string tableName, string key)
|
||||||
|
: base($"Localization key '{key}' not found in table '{tableName}'")
|
||||||
|
{
|
||||||
|
TableName = tableName;
|
||||||
|
Key = key;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 表名
|
||||||
|
/// </summary>
|
||||||
|
public string TableName { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 键名
|
||||||
|
/// </summary>
|
||||||
|
public string Key { get; }
|
||||||
|
}
|
||||||
@ -0,0 +1,22 @@
|
|||||||
|
namespace GFramework.Core.Abstractions.Localization;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 本地化表未找到异常
|
||||||
|
/// </summary>
|
||||||
|
public class LocalizationTableNotFoundException : LocalizationException
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 初始化表未找到异常
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="tableName">表名</param>
|
||||||
|
public LocalizationTableNotFoundException(string tableName)
|
||||||
|
: base($"Localization table '{tableName}' not found")
|
||||||
|
{
|
||||||
|
TableName = tableName;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 表名
|
||||||
|
/// </summary>
|
||||||
|
public string TableName { get; }
|
||||||
|
}
|
||||||
@ -1,4 +1,4 @@
|
|||||||
namespace GFramework.Core.Abstractions.logging;
|
namespace GFramework.Core.Abstractions.Logging;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 日志输出器接口,负责将日志条目写入特定目标
|
/// 日志输出器接口,负责将日志条目写入特定目标
|
||||||
@ -1,4 +1,4 @@
|
|||||||
namespace GFramework.Core.Abstractions.logging;
|
namespace GFramework.Core.Abstractions.Logging;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 日志过滤器接口,用于决定是否应该记录某条日志
|
/// 日志过滤器接口,用于决定是否应该记录某条日志
|
||||||
@ -1,4 +1,4 @@
|
|||||||
namespace GFramework.Core.Abstractions.logging;
|
namespace GFramework.Core.Abstractions.Logging;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 日志格式化器接口,用于将日志条目格式化为字符串
|
/// 日志格式化器接口,用于将日志条目格式化为字符串
|
||||||
@ -1,4 +1,4 @@
|
|||||||
namespace GFramework.Core.Abstractions.logging;
|
namespace GFramework.Core.Abstractions.Logging;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 定义日志记录接口,提供日志记录和级别检查功能
|
/// 定义日志记录接口,提供日志记录和级别检查功能
|
||||||
@ -1,4 +1,4 @@
|
|||||||
namespace GFramework.Core.Abstractions.logging;
|
namespace GFramework.Core.Abstractions.Logging;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 定义日志工厂接口,用于创建日志记录器实例
|
/// 定义日志工厂接口,用于创建日志记录器实例
|
||||||
@ -1,4 +1,4 @@
|
|||||||
namespace GFramework.Core.Abstractions.logging;
|
namespace GFramework.Core.Abstractions.Logging;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 定义日志工厂提供者的接口,用于创建具有指定名称和最小日志级别的日志记录器
|
/// 定义日志工厂提供者的接口,用于创建具有指定名称和最小日志级别的日志记录器
|
||||||
@ -1,4 +1,4 @@
|
|||||||
namespace GFramework.Core.Abstractions.logging;
|
namespace GFramework.Core.Abstractions.Logging;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 支持结构化日志的日志记录器接口
|
/// 支持结构化日志的日志记录器接口
|
||||||
@ -1,4 +1,4 @@
|
|||||||
namespace GFramework.Core.Abstractions.logging;
|
namespace GFramework.Core.Abstractions.Logging;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 日志上下文,用于在异步流中传递结构化属性
|
/// 日志上下文,用于在异步流中传递结构化属性
|
||||||
@ -1,4 +1,4 @@
|
|||||||
namespace GFramework.Core.Abstractions.logging;
|
namespace GFramework.Core.Abstractions.Logging;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 日志条目,包含完整的日志信息
|
/// 日志条目,包含完整的日志信息
|
||||||
@ -1,4 +1,4 @@
|
|||||||
namespace GFramework.Core.Abstractions.logging;
|
namespace GFramework.Core.Abstractions.Logging;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 定义日志级别的枚举,用于标识不同严重程度的日志消息
|
/// 定义日志级别的枚举,用于标识不同严重程度的日志消息
|
||||||
10
GFramework.Core.Abstractions/Model/IModel.cs
Normal file
10
GFramework.Core.Abstractions/Model/IModel.cs
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
using GFramework.Core.Abstractions.Architectures;
|
||||||
|
using GFramework.Core.Abstractions.Lifecycle;
|
||||||
|
using GFramework.Core.Abstractions.Rule;
|
||||||
|
|
||||||
|
namespace GFramework.Core.Abstractions.Model;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 模型接口,定义了模型的基本行为和功能
|
||||||
|
/// </summary>
|
||||||
|
public interface IModel : IContextAware, IArchitecturePhaseListener, IInitializable;
|
||||||
@ -1,4 +1,4 @@
|
|||||||
namespace GFramework.Core.Abstractions.pause;
|
namespace GFramework.Core.Abstractions.Pause;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 暂停处理器接口,由引擎层实现具体的暂停/恢复逻辑
|
/// 暂停处理器接口,由引擎层实现具体的暂停/恢复逻辑
|
||||||
@ -1,6 +1,6 @@
|
|||||||
using GFramework.Core.Abstractions.utility;
|
using GFramework.Core.Abstractions.Utility;
|
||||||
|
|
||||||
namespace GFramework.Core.Abstractions.pause;
|
namespace GFramework.Core.Abstractions.Pause;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 暂停栈管理器接口,管理嵌套暂停状态
|
/// 暂停栈管理器接口,管理嵌套暂停状态
|
||||||
@ -75,7 +75,9 @@ public interface IPauseStackManager : IContextUtility
|
|||||||
void UnregisterHandler(IPauseHandler handler);
|
void UnregisterHandler(IPauseHandler handler);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 暂停状态变化事件
|
/// 暂停状态变化事件。
|
||||||
|
/// 事件遵循标准 .NET 事件模式,事件源为触发通知的暂停管理器实例,
|
||||||
|
/// 事件数据由 <see cref="PauseStateChangedEventArgs"/> 提供。
|
||||||
/// </summary>
|
/// </summary>
|
||||||
event Action<PauseGroup, bool>? OnPauseStateChanged;
|
event EventHandler<PauseStateChangedEventArgs>? OnPauseStateChanged;
|
||||||
}
|
}
|
||||||
@ -1,4 +1,4 @@
|
|||||||
namespace GFramework.Core.Abstractions.pause;
|
namespace GFramework.Core.Abstractions.Pause;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 暂停组枚举,定义不同的暂停作用域
|
/// 暂停组枚举,定义不同的暂停作用域
|
||||||
@ -0,0 +1,30 @@
|
|||||||
|
namespace GFramework.Core.Abstractions.Pause;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 表示暂停状态变化事件的数据。
|
||||||
|
/// 该类型用于向事件订阅者传递暂停组以及该组变化后的暂停状态。
|
||||||
|
/// </summary>
|
||||||
|
public sealed class PauseStateChangedEventArgs : EventArgs
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 初始化 <see cref="PauseStateChangedEventArgs"/> 的新实例。
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="group">发生状态变化的暂停组。</param>
|
||||||
|
/// <param name="isPaused">暂停组变化后的新状态。</param>
|
||||||
|
public PauseStateChangedEventArgs(PauseGroup group, bool isPaused)
|
||||||
|
{
|
||||||
|
Group = group;
|
||||||
|
IsPaused = isPaused;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取发生状态变化的暂停组。
|
||||||
|
/// </summary>
|
||||||
|
public PauseGroup Group { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取暂停组变化后的新状态。
|
||||||
|
/// 为 <see langword="true"/> 表示进入暂停,为 <see langword="false"/> 表示恢复运行。
|
||||||
|
/// </summary>
|
||||||
|
public bool IsPaused { get; }
|
||||||
|
}
|
||||||
74
GFramework.Core.Abstractions/Pause/PauseToken.cs
Normal file
74
GFramework.Core.Abstractions/Pause/PauseToken.cs
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
namespace GFramework.Core.Abstractions.Pause;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 暂停令牌,唯一标识一个暂停请求
|
||||||
|
/// </summary>
|
||||||
|
public readonly struct PauseToken : IEquatable<PauseToken>
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 令牌 ID
|
||||||
|
/// </summary>
|
||||||
|
public Guid Id { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 是否为有效令牌
|
||||||
|
/// </summary>
|
||||||
|
public bool IsValid => Id != Guid.Empty;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 创建暂停令牌
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="id">令牌 ID,用于唯一标识暂停请求</param>
|
||||||
|
public PauseToken(Guid id)
|
||||||
|
{
|
||||||
|
Id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 创建无效令牌
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>返回一个 ID 为 Guid.Empty 的无效暂停令牌</returns>
|
||||||
|
public static PauseToken Invalid => new(Guid.Empty);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 判断当前令牌是否与另一个令牌相等
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="other">要比较的另一个暂停令牌</param>
|
||||||
|
/// <returns>如果两个令牌的 ID 相同则返回 true,否则返回 false</returns>
|
||||||
|
public bool Equals(PauseToken other) => Id.Equals(other.Id);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 判断当前对象是否为暂停令牌类型并与其相等
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="obj">要比较的对象</param>
|
||||||
|
/// <returns>如果对象是 PauseToken 类型且 ID 相同则返回 true,否则返回 false</returns>
|
||||||
|
public override bool Equals(object? obj) => obj is PauseToken other && Equals(other);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取令牌的哈希码
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>基于令牌 ID 计算的哈希值</returns>
|
||||||
|
public override int GetHashCode() => Id.GetHashCode();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 重载等于运算符,判断两个暂停令牌是否相等
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="left">左侧暂停令牌</param>
|
||||||
|
/// <param name="right">右侧暂停令牌</param>
|
||||||
|
/// <returns>如果两个令牌相等则返回 true,否则返回 false</returns>
|
||||||
|
public static bool operator ==(PauseToken left, PauseToken right) => left.Equals(right);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 重载不等于运算符,判断两个暂停令牌是否不相等
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="left">左侧暂停令牌</param>
|
||||||
|
/// <param name="right">右侧暂停令牌</param>
|
||||||
|
/// <returns>如果两个令牌不相等则返回 true,否则返回 false</returns>
|
||||||
|
public static bool operator !=(PauseToken left, PauseToken right) => !left.Equals(right);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 将暂停令牌转换为字符串表示形式
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>包含令牌 ID 信息的字符串</returns>
|
||||||
|
public override string ToString() => $"PauseToken({Id})";
|
||||||
|
}
|
||||||
@ -1,4 +1,4 @@
|
|||||||
namespace GFramework.Core.Abstractions.pool;
|
namespace GFramework.Core.Abstractions.Pool;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 对象池系统接口,定义了对象池的基本操作
|
/// 对象池系统接口,定义了对象池的基本操作
|
||||||
@ -1,4 +1,4 @@
|
|||||||
namespace GFramework.Core.Abstractions.pool;
|
namespace GFramework.Core.Abstractions.Pool;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 定义可池化对象的接口,提供对象在池中的生命周期管理方法
|
/// 定义可池化对象的接口,提供对象在池中的生命周期管理方法
|
||||||
@ -1,4 +1,4 @@
|
|||||||
namespace GFramework.Core.Abstractions.pool;
|
namespace GFramework.Core.Abstractions.Pool;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 对象池统计信息
|
/// 对象池统计信息
|
||||||
@ -1,4 +1,4 @@
|
|||||||
namespace GFramework.Core.Abstractions.properties;
|
namespace GFramework.Core.Abstractions.Properties;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 架构选项配置类,用于定义架构行为的相关配置选项。
|
/// 架构选项配置类,用于定义架构行为的相关配置选项。
|
||||||
@ -17,10 +17,4 @@ public sealed class ArchitectureProperties
|
|||||||
/// 默认值为 false,表示不启用严格验证。
|
/// 默认值为 false,表示不启用严格验证。
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool StrictPhaseValidation { get; set; }
|
public bool StrictPhaseValidation { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 启用 ECS(Entity Component System)功能的开关。
|
|
||||||
/// 当设置为 true 时,架构将启用 ECS 相关功能。
|
|
||||||
/// </summary>
|
|
||||||
public bool EnableEcs { get; set; }
|
|
||||||
}
|
}
|
||||||
@ -1,6 +1,6 @@
|
|||||||
using GFramework.Core.Abstractions.logging;
|
using GFramework.Core.Abstractions.Logging;
|
||||||
|
|
||||||
namespace GFramework.Core.Abstractions.properties;
|
namespace GFramework.Core.Abstractions.Properties;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 日志配置选项类,用于配置日志系统的相关参数
|
/// 日志配置选项类,用于配置日志系统的相关参数
|
||||||
@ -1,4 +1,4 @@
|
|||||||
namespace GFramework.Core.Abstractions.property;
|
namespace GFramework.Core.Abstractions.Property;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 可绑定属性接口,继承自只读可绑定属性接口,提供可读写的属性绑定功能
|
/// 可绑定属性接口,继承自只读可绑定属性接口,提供可读写的属性绑定功能
|
||||||
@ -1,6 +1,6 @@
|
|||||||
using GFramework.Core.Abstractions.events;
|
using GFramework.Core.Abstractions.Events;
|
||||||
|
|
||||||
namespace GFramework.Core.Abstractions.property;
|
namespace GFramework.Core.Abstractions.Property;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 只读可绑定属性接口,提供属性值的读取和变更监听功能
|
/// 只读可绑定属性接口,提供属性值的读取和变更监听功能
|
||||||
@ -1,4 +1,4 @@
|
|||||||
namespace GFramework.Core.Abstractions.query;
|
namespace GFramework.Core.Abstractions.Query;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 异步查询接口,定义了执行异步查询操作的方法
|
/// 异步查询接口,定义了执行异步查询操作的方法
|
||||||
@ -1,4 +1,4 @@
|
|||||||
namespace GFramework.Core.Abstractions.query;
|
namespace GFramework.Core.Abstractions.Query;
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -1,6 +1,6 @@
|
|||||||
using GFramework.Core.Abstractions.rule;
|
using GFramework.Core.Abstractions.Rule;
|
||||||
|
|
||||||
namespace GFramework.Core.Abstractions.query;
|
namespace GFramework.Core.Abstractions.Query;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 查询接口,定义了执行查询操作的契约
|
/// 查询接口,定义了执行查询操作的契约
|
||||||
@ -1,4 +1,4 @@
|
|||||||
namespace GFramework.Core.Abstractions.query;
|
namespace GFramework.Core.Abstractions.Query;
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -1,6 +1,6 @@
|
|||||||
using GFramework.Core.Abstractions.bases;
|
using GFramework.Core.Abstractions.Bases;
|
||||||
|
|
||||||
namespace GFramework.Core.Abstractions.registries;
|
namespace GFramework.Core.Abstractions.Registries;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 表示一个通用的注册表接口,用于根据键类型T获取值类型TR的对象
|
/// 表示一个通用的注册表接口,用于根据键类型T获取值类型TR的对象
|
||||||
@ -1,7 +1,7 @@
|
|||||||
using System.Collections.ObjectModel;
|
using System.Collections.ObjectModel;
|
||||||
using GFramework.Core.Abstractions.bases;
|
using GFramework.Core.Abstractions.Bases;
|
||||||
|
|
||||||
namespace GFramework.Core.Abstractions.registries;
|
namespace GFramework.Core.Abstractions.Registries;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 基于Dictionary的通用键值注册表基类
|
/// 基于Dictionary的通用键值注册表基类
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user