二进制格式化程序忽略程序集版本

5
我有以下方法来生成一个对象的哈希值。它的运行效果相当不错!但是当我改变程序集的版本时,即使对象相同,哈希值也会发生变化。
public static string GetHash(Object item)
{
    MemoryStream memoryStream = new MemoryStream();
    BinaryFormatter binaryFormatter = new BinaryFormatter();
    binaryFormatter.Serialize(memoryStream, item);
    binaryFormatter.AssemblyFormat = FormatterAssemblyStyle.Simple;

    HashAlgorithm hashAlgorithm = new MD5CryptoServiceProvider();
    memoryStream.Seek(0, SeekOrigin.Begin);

    return Convert.ToBase64String(hashAlgorithm.ComputeHash(memoryStream));
}

如何忽略程序集版本号?

1
对象不是相同的。在.NET中,类型不仅包括命名空间和类型名称,还包括它来自的程序集,其中包括[AssemblyVersion]。这是一种强大的DLL-Hell防范措施,以及一种强大的检查,防止反序列化不再匹配更改类的数据。您的哈希计算只是另一个检查,验证数据是否已更改,可能是不必要的。不,您不能忽略程序集版本。 - Hans Passant
2个回答

4
但是,当我更改程序集的版本时,即使对象相同,哈希值也会发生变化。使用BinaryFormatter时,这是预期的行为...它不能保证创建相同的输出 - 特别是因为它包含完整的类型信息(包括版本),所以在不同版本之间几乎肯定会发生变化。我建议考虑使用不包含类型信息的序列化程序; XmlSerializer、Json.NET或protobuf-net可能是不错的选择。

3

BinaryFormatter.AssemblyFormat 的文档说明如下:

获取或设置反序列化程序在查找和加载程序集方面的行为。

没有表明它对序列化路径有任何影响。

个人认为,我会避免使用这种散列方法 - 在我看来,它似乎非常脆弱。你无法控制被散列对象,或者以更稳定的方式进行散列吗?


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接