.NET 4.5 MethodInfo序列化破坏了变化

Adr*_*tti 8 .net serialization .net-4.5

问题

MethodInfo使用程序集的1.0版序列化的对象(具有私有字段)将不会使用该程序集的1.1版进行反序列化(SerializationException将抛出a,因为尚未找到所需的方法).

改变了什么?

我发现在.NET 4.5中,MemberInfo通道的序列化机制MemberInfoSerializationHolder已经改变.在过去(直到.NET 4.0),序列化数据是方法签名(通过简单获得MethodInfo.ToString()).根据.NET源代码中的评论,他们添加了第二个签名,SerializationToString()因为:

m_signature存储有时不明确的成员的ToString()表示.相同方法或属性的多重重载可以与ToString()相同.m_signature2存储SerializationToString()表示,该表示对于每个成员应该是唯一的.它仅由post 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(...);
Run Code Online (Sandbox Code Playgroud)

在这种情况下,反序列化失败,因为m_signature2无法找到签名,因为程序集名称包含版本信息,然后String.Equals()将不匹配MyAssembly, Version=1.0.0.0,MyAssembly, Version=1.1.0.0并将抛出异常.

这个问题

如果搜索失败(至少因为与现有代码的兼容性),我希望框架将失败回旧的搜索方法.我不明白为什么这个比较是用a做的,在程序集的所有版本都在运行时被解析(默认情况下会加载更新的版本),我同意它无法解决那里的程序集版本但是它如果严格搜索失败,可以删除/忽略它.String.Equals()

我知道序列化很糟糕MethodInfo但是此时此修复可能涉及太多的更改(无论是在体系结构还是代码中),并且没有人会在旧代码中开始重构(此外,对于新旧代码,必须保留对存档的二进制兼容性版本,两个方向).

到目前为止我没有尝试,但这个问题也适用于代表吗?是否有任何解决方案(具有属性或小代码更改)来解决此问题?

Adr*_*tti 1

最后我自己也没能完全解决这个问题。我尝试ISerializable使用自定义实现MemberInfoSerializationHolder来模仿旧行为(仅粘贴 4.0 版本中的代码)。它适用于存档,但不适用于此场景的旧(已部署)应用程序。我没有找到任何方法来解决这个问题,因为已经发布的应用程序将无法工作(除非应用补丁,但这不可行)。

我看到在较新的版本中实现发生了一些变化,无论如何,仅当有多个具有相同名称的方法(然后使用签名)时才会预设问题,否则仅选择第一个(也是唯一的)一个而不进行任何额外检查。