mirror of
https://github.com/GeWuYou/GFramework.git
synced 2026-03-25 21:34:28 +08:00
- 新增 Core API 参考文档,涵盖架构与模块、数据模型与系统、命令与查询等核心组件 - 添加事件系统接口详细文档,包括 IEvent、IEventBus、IUnRegister 等接口说明 - 提供完整的 API 使用示例路径、最佳实践与性能建议 - 包含架构图、依赖关系图与故障排查指南 - 添加测试用例参考与扩展方法说明 - [skip ci]
19 KiB
19 KiB
存储系统
**本文引用的文件列表** - [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)目录
简介
本文件面向GFramework存储系统,聚焦于FileStorage文件存储实现、ScopedStorage作用域存储策略、以及IStorage/IFileStorage/IScopedStorage接口的设计理念。文档涵盖文件读写流程、路径管理与安全校验、错误处理机制、作用域隔离与命名空间控制、以及在游戏开发中的典型应用场景(配置、存档、临时缓存)。同时提供配置选项、API参考与实践示例,并总结数据持久化的最佳实践、安全性与性能优化建议。
项目结构
存储系统由“抽象接口层”“具体实现层”“序列化器层”“应用集成层”组成:
- 抽象接口层:定义统一的存储契约(IStorage、IFileStorage、IScopedStorage)。
- 具体实现层:FileStorage(通用文件系统)、ScopedStorage(作用域包装器)、GodotFileStorage(Godot引擎专用)。
- 序列化器层: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.cs
- IFileStorage.cs
- IScopedStorage.cs
- ISerializer.cs
- FileStorage.cs
- ScopedStorage.cs
- GodotFileStorage.cs
- JsonSerializer.cs
- SettingsPersistence.cs
章节来源
- IStorage.cs
- IFileStorage.cs
- IScopedStorage.cs
- ISerializer.cs
- FileStorage.cs
- ScopedStorage.cs
- GodotFileStorage.cs
- JsonSerializer.cs
- ReadMe.md
- SettingsPersistence.cs
核心组件
- IStorage:统一的存储接口,定义读写、存在检查、异步操作与删除等能力。
- IFileStorage:面向文件系统的存储接口,继承自IStorage。
- IScopedStorage:作用域存储接口,继承自IStorage,提供命名空间隔离。
- FileStorage:基于文件系统的通用实现,支持同步/异步读写、路径安全校验、细粒度锁。
- ScopedStorage:作用域包装器,为所有键添加前缀,支持嵌套作用域。
- ISerializer/JsonSerializer:序列化器接口与JSON实现,负责对象与字符串的互转。
- SettingsPersistence:设置持久化业务组件,基于IStorage实现设置的加载/保存/删除。
章节来源
- IStorage.cs
- IFileStorage.cs
- IScopedStorage.cs
- FileStorage.cs
- ScopedStorage.cs
- ISerializer.cs
- JsonSerializer.cs
- SettingsPersistence.cs
架构总览
存储系统采用“接口抽象 + 多实现 + 装饰器包装”的架构:
- 接口层提供统一契约,屏蔽具体实现差异。
- 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
图表来源
- IStorage.cs
- IFileStorage.cs
- IScopedStorage.cs
- FileStorage.cs
- ScopedStorage.cs
- GodotFileStorage.cs
- ISerializer.cs
- JsonSerializer.cs
- SettingsPersistence.cs
组件详解
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延迟与锁等待,必要时引入异步与缓存。