在 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,因为每次启动应用程序时该函数的结果都会改变。