ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

AssetRipper 数据存储:从 3 个抽象看懂配置是怎么落盘的

AssetRipper 数据存储:从 3 个抽象看懂配置是怎么落盘的 AssetRipper 数据存储从 3 个抽象看懂配置是怎么落盘的【免费下载链接】AssetRipperGUI application to analyze game files项目地址: https://gitcode.com/GitHub_Trending/as/AssetRipper打开 AssetRipper 处理一份游戏文件时你会点导出、调处理参数。这些设置改完存在哪、下次启动怎么读回来AssetRipper 把这一层独立成了AssetRipper.Configuration子项目。读完本文你能看懂 FullConfiguration 里那些GetStoredValue/SetStoredValue调用到底在做什么并知道如何给项目加一份自定义配置。一次改个参数的操作逼出存储层要回答两个问题假设你想调一下处理参数里的某个开关。表面上只是一次赋值背后却跨了两个边界磁盘上是一份持久化文本内存里是一份强类型对象同一个 storage 里还塞着 ExportSettings、EngineResourceData 等其他键类型各不相同。所以存储层必须回答两件事键怎么定位值、值怎么在对象和字符串之间来回转。AssetRipper 把这两件事拆到两层里做一层叫DataStorage管键一层叫DataEntry的两个子类管值。第一层DataStorage 就是带类型约束的字典存储基类源码 不到 60 行核心签名如下public class DataStorageT where T : DataEntry { protected readonly Dictionarystring, T data []; public T? this[string key] { get; set; } public bool TryGetValueTValue(string key, out TValue? value) where TValue : T; public TValue GetValueTValue(string key) where TValue : T; public void Add(string key, T value); }约束T : DataEntry保证所有值都实现了Clear()这样DataStorage.Clear()才能一次性回收所有条目。项目里真正在用的只有两个子类SingletonDataStorage一个键对一个值如 ProcessingSettings和ListDataStorage一个键对一组值如待导出的文件路径。它们只是 DataStorage 的薄封装把常用 Add 重载写死成Liststring或IParsableT省得调用方每次手动 new 一个 DataSet。第二层DataInstance 与 DataSet 是带文本视图的值值容器从 值容器基类 开始分两条线DataInstanceT是单值DataSetT是列表两者都暴露一个关键属性 Textpublic sealed override string Text { get serializer.Serialize(Value); set Value serializer.Deserialize(value); }这就是整个存储层的序列化入口磁盘上是 string内存里是 T中间通过 Text 互相转。DataSetT额外提供一个StringAccessor把IReadOnlyListstring的视图直接套在列表上让你能像操作字符串数组一样操作强类型列表。值容器的三种口味对应三种序列化器同一个DataInstanceT骨架换不同的序列化器就是不同口味值容器序列化器数据类型典型用途StringDataInstanceStringDataSerializerstring纯字符串直接透传ParsableDataInstanceTParsableDataSerializerTIParsableT能从字符串解析的类型JsonDataInstanceTJsonDataSerializerT任意可 JSON 类型复杂对象JsonDataSerializer 里有一段耐人寻味的容错逻辑public override T Deserialize(string text) { if (string.IsNullOrEmpty(text)) return CreateNew(); try { return JsonSerializer.Deserialize(text, typeInfo) ?? CreateNew(); } catch { return CreateNew(); } }磁盘上的 JSON 损坏、字段缺失都不会让程序崩而是退回到CreateNew()给出的默认值。对加载用户配置文件这种场景这是务实的选择——宁可丢一份配置也别让整个应用起不来。一个真实例子FullConfiguration 里的 ProcessingSettings看 FullConfiguration 怎么把这一切串起来public ProcessingSettings ProcessingSettings { get SingletonData.GetStoredValueProcessingSettings(nameof(ProcessingSettings)); set SingletonData.SetStoredValue(nameof(ProcessingSettings), value); } // 构造里 SingletonData.Add(nameof(ProcessingSettings), new JsonDataInstanceProcessingSettings( SerializedSettingsContext.Default.ProcessingSettings));流程一目了然Add 时把ProcessingSettings对象包进JsonDataInstance塞进字典Get 时GetStoredValueT取出 DataInstance 再做一次类型断言。断言失败抛KeyNotFoundException这是编译器之外的最后一道兜底——键名拼错、类型用错都会在运行期暴露。写回磁盘时序列化器把 DataStorage 里每个值的 Text 拼起来读回时反过来。因为 Text 已经承担了对象 ↔ 字符串的转换落盘和反序列化都退化成纯字符串操作跟具体存储介质JSON、INI、YAML解耦。想自己加一份配置三步就够给 AssetRipper 加一个自定义配置项路径很短让新类型FooSettings能被JsonDataInstanceFooSettings装下即带无参构造在 FullConfiguration 的构造里SingletonData.Add(nameof(FooSettings), new JsonDataInstanceFooSettings(...))加一个 property 走GetStoredValue/SetStoredValue。如果新类型本身就有文本形态版本号、路径列表可以改走ParsableDataInstanceT这条线省掉一次 JSON 往返。参考 ParsableDataSerializer 里的IParsableT契约自己实现Parse和ToString即可接入。【免费下载链接】AssetRipperGUI application to analyze game files项目地址: https://gitcode.com/GitHub_Trending/as/AssetRipper创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表