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

19 KiB
Raw Blame History

存储系统

**本文引用的文件列表** - [IStorage.cs](file://GFramework.Core.Abstractions/storage/IStorage.cs) - [IFileStorage.cs](file://GFramework.Game.Abstractions/storage/IFileStorage.cs) - [IScopedStorage.cs](file://GFramework.Game.Abstractions/storage/IScopedStorage.cs) - [ISerializer.cs](file://GFramework.Game.Abstractions/serializer/ISerializer.cs) - [FileStorage.cs](file://GFramework.Game/storage/FileStorage.cs) - [ScopedStorage.cs](file://GFramework.Game/storage/ScopedStorage.cs) - [JsonSerializer.cs](file://GFramework.Game/serializer/JsonSerializer.cs) - [ReadMe.md](file://GFramework.Game/storage/ReadMe.md) - [GodotFileStorage.cs](file://GFramework.Godot/storage/GodotFileStorage.cs) - [CachedStorage.cs](file://GFramework.Game/README.md) - [SettingsPersistence.cs](file://GFramework.Game/setting/SettingsPersistence.cs) - [ISettingsPersistence.cs](file://GFramework.Game.Abstractions/setting/ISettingsPersistence.cs)

目录

  1. 简介
  2. 项目结构
  3. 核心组件
  4. 架构总览
  5. 组件详解
  6. 依赖关系分析
  7. 性能与优化
  8. 故障排查指南
  9. 结论
  10. 附录

简介

本文件面向GFramework存储系统聚焦于FileStorage文件存储实现、ScopedStorage作用域存储策略、以及IStorage/IFileStorage/IScopedStorage接口的设计理念。文档涵盖文件读写流程、路径管理与安全校验、错误处理机制、作用域隔离与命名空间控制、以及在游戏开发中的典型应用场景配置、存档、临时缓存。同时提供配置选项、API参考与实践示例并总结数据持久化的最佳实践、安全性与性能优化建议。

项目结构

存储系统由“抽象接口层”“具体实现层”“序列化器层”“应用集成层”组成:

  • 抽象接口层定义统一的存储契约IStorage、IFileStorage、IScopedStorage
  • 具体实现层FileStorage通用文件系统、ScopedStorage作用域包装器、GodotFileStorageGodot引擎专用
  • 序列化器层ISerializer及JsonSerializer负责对象与文本的双向转换。
  • 应用集成层SettingsPersistence等业务组件通过IStorage进行设置的加载/保存/删除。
graph TB
subgraph "抽象接口层"
IStorage["IStorage 接口"]
IFileStorage["IFileStorage 接口"]
IScopedStorage["IScopedStorage 接口"]
ISerializer["ISerializer 接口"]
end
subgraph "实现层"
FileStorage["FileStorage 实现"]
ScopedStorage["ScopedStorage 实现"]
GodotFileStorage["GodotFileStorage 实现"]
end
subgraph "序列化器层"
JsonSerializer["JsonSerializer 实现"]
end
subgraph "应用集成层"
SettingsPersistence["SettingsPersistence 业务组件"]
end
IFileStorage --> IStorage
IScopedStorage --> IStorage
FileStorage --> IFileStorage
ScopedStorage --> IScopedStorage
GodotFileStorage --> IStorage
FileStorage --> ISerializer
GodotFileStorage --> ISerializer
JsonSerializer --> ISerializer
SettingsPersistence --> IStorage

图表来源

章节来源

核心组件

  • IStorage统一的存储接口定义读写、存在检查、异步操作与删除等能力。
  • IFileStorage面向文件系统的存储接口继承自IStorage。
  • IScopedStorage作用域存储接口继承自IStorage提供命名空间隔离。
  • FileStorage基于文件系统的通用实现支持同步/异步读写、路径安全校验、细粒度锁。
  • ScopedStorage作用域包装器为所有键添加前缀支持嵌套作用域。
  • ISerializer/JsonSerializer序列化器接口与JSON实现负责对象与字符串的互转。
  • SettingsPersistence设置持久化业务组件基于IStorage实现设置的加载/保存/删除。

章节来源

架构总览

存储系统采用“接口抽象 + 多实现 + 装饰器包装”的架构:

  • 接口层提供统一契约,屏蔽具体实现差异。
  • FileStorage/GodotFileStorage分别适配通用文件系统与Godot虚拟路径。
  • ScopedStorage通过装饰器模式为任意IStorage增加命名空间隔离。
  • SettingsPersistence等业务组件仅依赖IStorage便于替换与扩展。
classDiagram
class IStorage {
+Exists(key) bool
+ExistsAsync(key) Task~bool~
+Read~T~(key) T
+Read~T~(key, defaultValue) T
+ReadAsync~T~(key) Task~T~
+Write~T~(key, value) void
+WriteAsync~T~(key, value) Task
+Delete(key) void
}
class IFileStorage
class IScopedStorage
class FileStorage
class ScopedStorage
class GodotFileStorage
class ISerializer
class JsonSerializer
class SettingsPersistence
IFileStorage --|> IStorage
IScopedStorage --|> IStorage
FileStorage ..|> IFileStorage
ScopedStorage ..|> IScopedStorage
GodotFileStorage ..|> IStorage
FileStorage --> ISerializer
GodotFileStorage --> ISerializer
JsonSerializer ..|> ISerializer
SettingsPersistence --> IStorage

图表来源

组件详解

FileStorage 文件存储实现

  • 设计目标:提供基于文件系统的可靠持久化能力,支持同步/异步读写、路径安全校验、细粒度锁保证线程安全。
  • 关键特性:
    • 路径安全:禁止“..”路径逃逸;清理非法文件名字符;自动创建目录。
    • 锁机制:按路径生成独立锁对象,避免跨键竞争,提升并发性能。
    • 序列化通过ISerializer完成对象与字符串的转换。
    • 扩展名:默认“.dat”可通过构造参数定制。
  • 主要方法与流程:
    • 路径转换ToPath规范化分隔符、清理段名、拼接根路径与扩展名。
    • 读取Read/ReadAsync先加锁再读取文件内容最后反序列化。
    • 写入Write/WriteAsync先序列化再加锁写入文件。
    • 存在检查Exists/ExistsAsync加锁判断文件是否存在。
    • 删除Delete加锁删除文件。
  • 错误处理:
    • 读取不存在键时抛出FileNotFoundException。
    • 读取重载Read(key, defaultValue)提供默认值避免异常。
    • 路径校验失败抛出ArgumentException。
  • 性能要点:
    • 异步读写仍需加锁但IO可异步进行减少阻塞。
    • 并发访问不同键可并行,同一键串行执行。
flowchart TD
Start(["调用 Read<T>(key)"]) --> ToPath["ToPath(key)<br/>规范化/清理/拼接路径"]
ToPath --> Lock["获取/创建键级锁"]
Lock --> CheckExist{"文件存在?"}
CheckExist --> |否| ThrowErr["抛出 FileNotFoundException"]
CheckExist --> |是| ReadFile["读取文件内容"]
ReadFile --> Deserialize["反序列化为 T"]
Deserialize --> Return["返回结果"]
ThrowErr --> End(["结束"])
Return --> End

图表来源

章节来源

ScopedStorage 作用域存储策略

  • 设计目标:通过前缀为所有键添加命名空间隔离,实现逻辑分组与数据范围控制,支持嵌套作用域。
  • 关键特性:
    • 前缀拼接Key(key)将prefix与key组合为“prefix/key”。
    • 嵌套作用域Scope(scope)返回新的ScopedStorage前缀叠加。
    • 透明包装所有IStorage操作均转发到底层inner存储。
    • 同步/异步:与底层存储保持一致的异步能力。
  • 使用场景:
    • 将玩家数据、游戏存档、全局设置分组到不同作用域,避免键冲突。
    • 嵌套作用域用于更细粒度的组织如settings/audio/master_volume
  • 注意事项:
    • 前缀为空时直接使用原键。
    • 与底层存储共享物理存储,注意键冲突与命名规范。
sequenceDiagram
participant Client as "客户端"
participant Scoped as "ScopedStorage"
participant Inner as "内部存储(IStorage)"
Client->>Scoped : Write(key, value)
Scoped->>Scoped : Key(key) -> "prefix/key"
Scoped->>Inner : Write("prefix/key", value)
Inner-->>Scoped : 完成
Scoped-->>Client : 返回

图表来源

章节来源

接口设计IStorage/IFileStorage/IScopedStorage

  • IStorage定义统一的读写、存在检查、异步与删除能力是所有存储实现的基础契约。
  • IFileStorage面向文件系统的扩展接口强调文件语义扩展名、路径等
  • IScopedStorage强调命名空间隔离与作用域管理便于多模块/多功能的数据分区。
  • 设计理念:
    • 抽象先行:通过接口屏蔽实现细节,便于替换与扩展。
    • 统一契约所有实现遵循相同的API降低学习成本与迁移成本。
    • 可组合通过装饰器如ScopedStorage增强功能不侵入核心实现。

章节来源

序列化器ISerializer/JsonSerializer

  • ISerializer定义Serialize/Deserialize通用方法解耦存储与序列化技术。
  • JsonSerializer基于Newtonsoft.Json实现提供对象与JSON字符串的互转。
  • 使用建议:
    • 选择与数据结构匹配的序列化器JSON适合结构化数据二进制/自定义格式适合性能敏感场景)。
    • 注意反序列化失败时的异常处理与默认值策略。

章节来源

应用集成SettingsPersistence

  • 通过IStorage实现设置的异步加载、保存、存在检查与删除。
  • 与事件系统配合,发出加载/应用/保存等事件,便于观察状态变化。
  • 适用于游戏配置、音量、难度等设置的持久化管理。

章节来源

依赖关系分析

  • FileStorage依赖ISerializer进行序列化依赖路径工具与文件系统API使用ConcurrentDictionary维护键级锁。
  • ScopedStorage依赖IStorage通过装饰器模式透明包装任何存储实现。
  • SettingsPersistence依赖IStorage与事件系统实现设置的生命周期管理。
  • GodotFileStorage为Godot引擎特化实现兼容res://与user://虚拟路径提供Godot FileAccess支持。
graph LR
FileStorage --> ISerializer
ScopedStorage --> IStorage
GodotFileStorage --> ISerializer
SettingsPersistence --> IStorage

图表来源

章节来源

性能与优化

  • 并发与锁:
    • FileStorage按键级锁不同键可并行同一键串行避免竞态。
    • GodotFileStorage同理按键级锁保障线程安全。
  • 异步IO
    • FileStorage/ScopedStorage在读取时可使用异步IO注意锁范围
    • GodotFileStorage ReadAsync通过Task.Run包装同步读取简化调用。
  • 缓存策略:
    • 可使用CachedStorage对热点数据进行内存缓存减少重复IO。
    • 缓存过期时间可配置默认5分钟支持清空缓存与清空存储。
  • 写入优化:
    • 批量写入优于频繁小写入;可缓冲后再一次性写入。
    • 合理拆分键层级,避免单文件过大导致读写压力集中。
  • 路径与序列化:
    • 使用合理扩展名与目录结构,便于备份与迁移。
    • 选择合适的序列化器,平衡可读性、体积与性能。

章节来源

故障排查指南

  • 常见问题与定位:
    • “存储键不存在”FileStorage读取会抛出FileNotFoundException建议使用Read(key, defaultValue)提供默认值。
    • “路径包含‘..ToPath会拒绝包含“..”的键抛出ArgumentException请使用合法路径。
    • “文件名包含非法字符”SanitizeSegment会替换非法字符为下划线请避免使用不可用字符。
    • “权限不足”:确保程序对存储目录具有读写权限。
    • “序列化失败”JsonSerializer反序列化失败会抛出ArgumentException检查数据格式与字段映射。
  • 调试建议:
    • 在关键节点记录日志(键、路径、序列化前后大小)。
    • 使用ScopedStorage隔离不同模块缩小问题范围。
    • 对高频读写键进行缓存减少IO波动。

章节来源

结论

GFramework存储系统通过清晰的接口抽象与多种实现为游戏开发提供了灵活、安全且高性能的数据持久化方案。FileStorage提供通用文件存储能力ScopedStorage实现命名空间隔离与作用域管理ISerializer解耦序列化技术SettingsPersistence将存储与业务流程结合。配合缓存与异步IO策略可在保证一致性的同时提升性能与可维护性。

附录

API参考IStorage/IFileStorage/IScopedStorage

  • IStorage
    • Exists(key): 检查键是否存在
    • ExistsAsync(key): 异步检查
    • Read(key): 读取键值
    • Read(key, defaultValue): 读取键值或默认值
    • ReadAsync(key): 异步读取
    • Write(key, value): 写入键值
    • WriteAsync(key, value): 异步写入
    • Delete(key): 删除键
  • IFileStorage继承IStorage面向文件系统
  • IScopedStorage继承IStorage提供作用域包装

章节来源

配置与使用示例

  • FileStorage
    • 构造FileStorage(rootPath, serializer, extension=".dat")
    • 示例:写入/读取/异步读取/存在检查/删除
  • ScopedStorage
    • 构造ScopedStorage(inner, prefix)
    • 示例:作用域前缀、嵌套作用域、异步操作
  • SettingsPersistence
    • 异步加载/保存/存在检查/删除;发送事件通知

章节来源

最佳实践

  • 命名与分层:使用有意义的键层级与作用域,避免键冲突。
  • 默认值策略:读取时提供默认值,避免异常传播。
  • 缓存与批处理:对热点数据启用缓存;合并多次写入为批量写入。
  • 安全与合规:严格校验键与路径,避免路径逃逸;定期备份重要数据。
  • 性能监控关注IO延迟与锁等待必要时引入异步与缓存。