.NET 4.5 MethodInfo 序列化重大更改 [英] .NET 4.5 MethodInfo serialization breaking change

查看:17
本文介绍了.NET 4.5 MethodInfo 序列化重大更改的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

An object (with a private MethodInfo field) serialized with version 1.0 of an assembly won't be deserialized with the version 1.1 of that assembly (a SerializationException will be thrown because required method has not been found).

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

I found that in .NET 4.5 the serialization mechanism of a MemberInfo via MemberInfoSerializationHolder has been changed. In the past (up to .NET 4.0) the serialized data was the method signature (obtained with a simple MethodInfo.ToString()). According to comments in the .NET source code they added a second signature obtained via SerializationToString() because:

m_signature 存储有时不明确的成员的 ToString() 表示.相同方法或属性的多重重载可以相同 ToString().m_signature2 存储对于每个成员应该是唯一的 SerializationToString() 表示.它仅由 4.0 后的 CLR 版本编写和使用.

m_signature stores the ToString() representation of the member which is sometimes ambiguous. Mulitple overloads of the same methods or properties can identical ToString(). m_signature2 stores the SerializationToString() representation which should be unique for each member. It is only written and used by post 4.0 CLR versions.

对于我所看到的 MemberInfoSerializationHolder.GetRealObject() 使用此(简化)代码来解析该方法(来自 .NET 源代码):

For what I can see the MemberInfoSerializationHolder.GetRealObject() uses this (simplified) code to resolve the method (from .NET source code):

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 带有 MyAssembly, Version=1.1.0.0 并且会抛出异常.

In this case the deserialization fails because the m_signature2 signature can't be found because assembly name contains version information then String.Equals() won't match MyAssembly, Version=1.0.0.0 with MyAssembly, Version=1.1.0.0 and an exception will be thrown.

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

I would expect the Framework will fail back to old search method if the new search fails (at least because of compatibility with existing code). I don't understand why this comparison is made with a String.Equals(), after all the version of an assembly is resolved at run-time (and newer version will be loaded by default), I agree it can't resolve the assembly version there but it may remove/ignore it if the strict search fails.

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

I know it's terrible to serialize a MethodInfo but at this moment this fix may involve too many changes (both in architecture and code) and no one would start this refactoring in that old code (moreover binary compatibility for archives must be kept for both old and new versions, in both directions).

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

So far I didn't try but is this issue applicable to delegates too? Is there any solution (with attributes or with small code changes) to workaround this problem?

推荐答案

最后我自己还是没能彻底解决这个问题.我尝试使用 MemberInfoSerializationHoldercustom 实现来实现 ISerializable 以模仿旧行为(只是粘贴 4.0 版本的代码).它适用于档案,但不适用于这种情况下的旧(已部署)应用程序.我没有找到任何方法来解决这个问题,因为已经发布的应用程序将无法运行(除非应用了补丁但这是不可行的).

Finally I've not been able to completely solve this issue by myself. I tried to implement ISerializable using a custom implementation of MemberInfoSerializationHolder to mimic the old behavior (just pasted code from 4.0 version). It works fine for new archives but it won't work with old (deployed) applications for this scenario. I didn't find any way to solve this issue because already shipped applications won't work (unless a patch is applied but this was not viable).

我看到在较新的版本中实现略有变化,无论如何问题是预设的,只有当有多个具有相同名称的方法(然后使用签名)时,否则只选择第一个(也是唯一的)一个,无需任何额外检查.

I saw implementation changed little bit over in newer builds anyway issue is preset only if there is more than one method with same name (signature is then used) otherwise just the first (and only) one is picked without any extra check.

这篇关于.NET 4.5 MethodInfo 序列化重大更改的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆