反序列化向后兼容性兼容性、序列化

2023-09-02 21:45:25 作者:心城以北

我想反序列化SomeClass的一个应用程序的旧版本。我得到这个下面异常

I am trying to deserialize "SomeClass" with an older version of an application. I get this below exception

System.Runtime.Serialization.SerializationException:在的ObjectManager发现链接地址信息的无效号码。这通常表示在格式化的问题。

System.Runtime.Serialization.SerializationException: The ObjectManager found an invalid number of fixups. This usually indicates a problem in the Formatter.

反序列化抛出异常,当我的连载0.9版本并尝试为使用反序列化版本0.8 。我以为 OptionalField 属性会做的伎俩,但事实并非如此。

Deserialization throws exception when I serialize version 0.9 and try to deserialize using version 0.8. I thought the OptionalField attribute would do the trick, but it didn't.

// Version 0.8
[Serializable()]
class Foo{
  Bar b;
} 

// Version 0.9
[Serializable()]
class Foo{
  Bar b;
  [OptionalField]
  Zoo z;
}

既然我不能改变的0.8版本,我应该怎么添加更多的状态Foo对象,使得previous版本可以反序列化一切可能?

Given that I cannot change version 0.8, how should I add more state to Foo object such that previous versions can deserialize whatever they can?

任何指针将是非常美联社preciated。

Any pointer will be really appreciated.

更新1 酒吧和动物园等类,它们是可序列化,并包含散列表和其他序列化的东西。一切都在序列化这些类。 另外,我没有任何支柱。

Update 1 Bar and Zoo are other classes which are serializable and contains Hashtables and other serializable stuff. Everything is serializable in those classes. Also, I don't have any struts.

推荐答案

首先,从来就不曾使用CLR的序列化功能的任何类似长期储存。我们犯类似的错误,通常一次,把对象在数据库中的BLOB字段并轻拍自己在后面想我们很聪明。然后CLR得到一个补丁或者我们的组件更改版本,你就完了。所以,不要做。

First, never NEVER use the CLR's serialization functions for anything that resembles long-term storage. We make that mistake usually once, put objects in a blob database field and pat ourselves in the back thinking we're clever. And then the CLR gets a patch or our assemblies change versions and you're screwed. So don't do it.

如果你仍然想这样做,管理问题的最好的方法是创建你自己的 SerializationBinder 看起来是这样的:

If you still want to do it, the best way to manage the problem is to create your own SerializationBinder that looks something like this:

public sealed class CustomBinder : SerializationBinder {

    public override Type BindToType(string assemblyName, string typeName) {

        Type typeToDeserialize = null;

        if (typeName.IndexOf("SomeType") != -1) {
            typeToDeserialize = typeof(Foo.Bar.Bax.NewType);
        }
        else if (typeName.IndexOf("SomeOtherType") != -1) {
            typeToDeserialize = typeof(Foo.Bar.Bax.SomeOtherNewType);
        }
        else {
            // ... etc
        }

        return typeToDeserialize;
    }
}

设置你使用之前,反序列化,使其覆盖默认格式化的文件夹属性。

请注意,我不是提供一个下拉式的解决方案,在这里,我建议如何解决这个问题。一旦你已经转换了无论你做什么的,研究其他的序列化技术,如protobuf的,或者自己编写。无论哪种方式,你不应该依赖于CLR长期序列化支持。

Note that I'm not offering a drop-in solution here, I'm recommending how to solve the problem. Once you've converted out of whatever you're doing, investigate other serialization technologies like protobuf, or write your own. Either way you should never rely on the CLR for long-term serialization support.