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

时间:2013-01-07 15:15:15

标签: .net serialization .net-4.5

问题

使用该程序集的1.1版序列化的程序集(具有私有MethodInfo字段)将不会使用该程序集的1.1版进行反序列化(因为所需的方法尚未抛出SerializationException被发现了。)

有什么改变?

我发现在.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(...);

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

问题

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

我知道序列化MethodInfo很糟糕但是此时此修复可能涉及太多更改(在架构和代码中)并且没有人会在旧代码中启动此重构(此外,对于归档的二进制兼容性)必须保留旧版和新版两个方向。)

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

2 个答案:

答案 0 :(得分:2)

我能想到的最好方法是实施ISerializableMSDN

在具有MethodInfo属性的对象上实现此接口,可以完全控制序列化/反序列化。

缺点是您还必须以某种通用方式处理所有其他属性。但是应该可行。

答案 1 :(得分:1)

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

我看到实现在新版本中稍微改了一下,无论如何只有当有多个具有相同名称的方法(然后使用签名)时才会预设问题,否则只选择第一个(也是唯一的)没有任何额外检查。