问题
一个对象(带有私有MethodInfo
使用程序集 1.0 版本序列化的字段)不会使用该程序集的 1.1 版本(aSerializationException
将被抛出,因为尚未找到所需的方法)。
发生了什么变化?
我发现.NET 4.5中的序列化机制MemberInfo
via MemberInfoSerializationHolder
已经变了。在过去(直到 .NET 4.0),序列化数据是方法签名(通过简单的方法获得)MethodInfo.ToString()
)。
根据 .NET 源代码中的注释,他们添加了通过以下方式获得的第二个签名SerializationToString()
因为:
m_signature 存储成员的 ToString() 表示形式,该表示形式有时是不明确的。相同方法或属性的多个重载可以相同的 ToString()。 m_signature2 存储 SerializationToString() 表示形式,该表示形式对于每个成员应该是唯一的。它仅由 4.0 之后的 CLR 版本编写和使用。
对于我所看到的MemberInfoSerializationHolder.GetRealObject()
使用此(简化的)代码来解析该方法(来自 .NET 源代码):
for (int i = 0; i < methods.Length; i++)
{
if (m_signature2 != null) // SerializationToString() signature
{
if (((RuntimeMethodInfo)methods[i]).SerializationToString().Equals(m_signature2))
{
methodInfo = methods[i];
break;
}
}
else
{
if (methods[i].ToString().Equals(m_signature))
{
methodInfo = methods[i];
break;
}
}
}
if (methodInfo == null)
throw new SerializationException(...);
在这种情况下,反序列化失败,因为m_signature2
找不到签名,因为程序集名称包含版本信息String.Equals()
不会匹配MyAssembly, Version=1.0.0.0
with MyAssembly, Version=1.1.0.0
并且会抛出异常。
问题
我预计框架会失败old搜索方法,如果new搜索失败(至少因为与现有代码的兼容性)。我不明白为什么要与String.Equals()
,在运行时解析了程序集的所有版本之后(默认情况下将加载较新的版本),我同意它无法解析那里的程序集版本,但如果strict搜索失败。
我知道连载起来很糟糕MethodInfo
但目前此修复可能涉及太多更改(架构和代码方面),并且没有人会在旧代码中开始这种重构(此外,必须在新旧版本两个方向上保持存档的二进制兼容性)。
到目前为止我还没有尝试过,但是这个问题也适用于代表吗?
是否有任何解决方案(使用属性或小的代码更改)来解决此问题?