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

查看:154
本文介绍了.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,版本= 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 搜索失败,框架将无法恢复到 old 搜索方法因为与现有代码兼容)。我不明白为什么在运行时解析了程序集的所有版本之后,会使用 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?

推荐答案

最后,我是我自己无法完全解决此问题。我尝试使用 MemberInfoSerializationHolder custom 实现来实现 ISerializable 来模仿旧的行为(只是粘贴了4.0版中的代码)。对于 new 归档文件,它工作正常,但在这种情况下,它不适用于旧的(已部署的)应用程序。
我没有找到解决此问题的任何方法,因为已经发布的应用程序将无法正常工作(除非应用了补丁程序,但这是不可行的。)。

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天全站免登陆