【发布时间】:2022-08-24 18:36:46
【问题描述】:
我们的应用程序使用状态的序列化快照,它只是类在某个时间点的序列化版本。
我们在类上有一个版本号,每次修改类时都会增加一个版本号,我们用它来指示以前的快照无效并忽略它们。
偶尔有人忘记增加版本,我们会得到错误。
我想为类的结构生成一个散列并用它来存储快照,所以如果它发生变化,那么以前的快照将自动失效。
我已经考虑过使用 Roslyn 加载类的表示并在其上调用 GetHashCode,但无法弄清楚如何将现有类加载到 Roslyn。
此外,我还研究了 Visual Studio 在构建时生成哈希:https://docs.microsoft.com/en-us/archive/msdn-magazine/2017/march/visual-studio-hashing-source-code-files-with-visual-studio-to-assure-file-integrity 但这似乎有点矫枉过正。
那么如何生成现有 C# 类结构(不是类的实例)的哈希?
更新:
这是一个没有方法的 POCO。使快照无效的更改包括添加、删除或重命名属性。
-
什么样的更改会使您的快照无效?仅更改字段还是更改方法声明甚至更改实现?
-
序列化成不关心额外属性的格式怎么样,比如 JSON?如果 V1 有 2 个属性(姓名、地址)而 V2 有 3 个属性(姓名、地址、dob),那么 JSON 会将相同的数据序列化到两者中,没有任何问题。
-
如果有人忘记更新版本号,那么在我看来,你错过了一个单元测试用例。
-
您可以使用Source Generator。你可以让你的班级成为部分班级。生成器将创建第二个部分类文件,其中包含类的属性或带有哈希码的字符串常量。
-
必须在每次编译时使类无效(即使没有更改)和更保守地忽略类获得某种不一定重要的更改之间取得平衡。每次以任何方式更改类时更改一个数字是最简单的(也是最保守的),但这也会计算外部观察者不可见或无关紧要的更改(添加 cmets、添加私有字段以缓存数据、添加属性),这可能是不可取的。