在 C# 中生成 class 结构的散列
Generating hash of a class structure in C#
我们的应用程序使用状态的序列化快照,它只是 class 在某个时间点的序列化版本。
我们在 class 上有一个版本号,每次修改 class 时我们都会增加它,我们用它来表示以前的快照无效并忽略它们。
有时有人忘记增加版本,我们就会出错。
我想为 class 的结构生成一个散列,并用它来存储快照,所以如果它发生变化,那么以前的快照将自动失效。
我已经考虑过使用 Roslyn 来加载 class 的表示并在其上调用 GetHashCode 但无法弄清楚如何将现有的 class 加载到 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# class 结构(不是 class 的实例)的散列?
更新:
这是一个没有方法的 POCO。使快照无效的更改包括添加、删除或重命名属性。
我建议使用反射来实现。
大致如下:
private int GetHashOfClass(Type myType)
{
int hash = 0;
foreach (var f in myType.GetMembers(BindingFlags.Public | BindingFlags.NonPublic))
{
if (f.MemberType == MemberTypes.Field ||
(f.MemberType & MemberTypes.Property) != 0)
{
hash ^= CreateHash(f.Name);
}
if (f is FieldInfo fi)
{
hash ^= CreateHash(fi.FieldType.Name);
}
}
return hash;
}
从 class 的字段和属性生成哈希码。 CreateHash
只是一个从字符串生成散列的函数。 不要使用现有的string.GetHashCode
,因为每次启动应用程序时该函数的结果都会改变。
我们的应用程序使用状态的序列化快照,它只是 class 在某个时间点的序列化版本。
我们在 class 上有一个版本号,每次修改 class 时我们都会增加它,我们用它来表示以前的快照无效并忽略它们。
有时有人忘记增加版本,我们就会出错。
我想为 class 的结构生成一个散列,并用它来存储快照,所以如果它发生变化,那么以前的快照将自动失效。
我已经考虑过使用 Roslyn 来加载 class 的表示并在其上调用 GetHashCode 但无法弄清楚如何将现有的 class 加载到 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# class 结构(不是 class 的实例)的散列?
更新:
这是一个没有方法的 POCO。使快照无效的更改包括添加、删除或重命名属性。
我建议使用反射来实现。
大致如下:
private int GetHashOfClass(Type myType)
{
int hash = 0;
foreach (var f in myType.GetMembers(BindingFlags.Public | BindingFlags.NonPublic))
{
if (f.MemberType == MemberTypes.Field ||
(f.MemberType & MemberTypes.Property) != 0)
{
hash ^= CreateHash(f.Name);
}
if (f is FieldInfo fi)
{
hash ^= CreateHash(fi.FieldType.Name);
}
}
return hash;
}
从 class 的字段和属性生成哈希码。 CreateHash
只是一个从字符串生成散列的函数。 不要使用现有的string.GetHashCode
,因为每次启动应用程序时该函数的结果都会改变。