配置仓储
IConfigRepository 负责从 MOD 目录加载配置、按类型分组缓存、计算哈希。
核心概念
- 分组:按配置类型分组,如
CharacterConfig对应Character/目录 - 项:分组内的单个配置文件,用
itemId标识 - 键:
(分组类型, itemId)唯一确定一份配置
注册与加载
// 注册分组
repo.Add(typeof(CharacterConfig), (typeof(CharacterData), isRoot: false));
// 扫描所有已注册分组并加载
repo.Load();
Add 只声明分组的存在和读取方式,不触发加载。Load 才会扫描目录。
目录约定
Mods/
└── {modId}/
├── Character/ # 分组目录 = 类型名去掉前缀
│ ├── chestnut.json
│ └── chestnut.yaml
└── Weapon/
└── 83079.json
isRoot: true 时从 Mods/{modId}/ 根目录直接查找,不进入子目录。
查询
// 单个查询
var data = repo.GetValue<CharacterConfig, CharacterData>("chestnut");
// 尝试查询
if (repo.TryGetValue<CharacterConfig, CharacterData>("chestnut", out var data))
{
// 使用 data
}
// 遍历某分组所有项
foreach (Id id in repo.GetAllId<CharacterConfig>())
{
Console.WriteLine(id.ItemId);
}
// 所有分组类型
foreach (Type t in repo.GetAllConfigType())
{
Console.WriteLine(t.Name);
}
哈希
Sha256 属性提供所有已加载配置文件的整体哈希:
string hash = repo.Sha256;
将所有文件的 SHA256 排序后拼接再取哈希,与文件加载顺序无关。
用途:
- 热重载时判断配置是否有变化
- 存档时记录配置版本
- 客户端 / 服务器一致性校验
线程安全
- 内部使用
ConcurrentDictionary保存状态 - 加载与查询可并发进行
- 同一项被多个线程同时加载时,只有一个线程成功,其余返回
false - 枚举结果是调用瞬间的快照
生命周期
典型用法:
启动阶段(可并发)
├─ Add 注册所有分组
└─ Load 扫描并加载
运行阶段(只读)
├─ GetValue / TryGetValue
└─ GetAllId / GetAllConfigType
如果运行期需要热加载,可以再次调用 Load 或 Load(Type, Type, string) 加载单项。