C# 是否可以使用旧的二进制文件反序列化新的派生类?

C# 是否可以使用旧的二进制文件反序列化新的派生类?,c#,serialization,C#,Serialization,在我的项目中,我有一个以二进制格式序列化到磁盘的类 由于一些新的需求,我需要创建一个从原始类派生的新类 乙二醇 当我尝试反序列化一个只包含Sample对象的旧文件时,它在当前程序集中工作正常。这意味着存在向后兼容性。但是,当我尝试使用以前版本的程序集应用程序反序列化包含DerivedSample对象的文件时,会崩溃。这意味着需要考虑向前兼容性 可以说从文件的新版本中只读取对象的基类部分吗 可以说只读 来自新对象的对象的基类部分 文件的版本 在这种情况下,最好将对象反序列化为Sample,然后在D

在我的项目中,我有一个以二进制格式序列化到磁盘的类

由于一些新的需求,我需要创建一个从原始类派生的新类

乙二醇

当我尝试反序列化一个只包含Sample对象的旧文件时,它在当前程序集中工作正常。这意味着存在向后兼容性。但是,当我尝试使用以前版本的程序集应用程序反序列化包含DerivedSample对象的文件时,会崩溃。这意味着需要考虑向前兼容性

可以说从文件的新版本中只读取对象的基类部分吗

可以说只读 来自新对象的对象的基类部分 文件的版本

在这种情况下,最好将对象反序列化为
Sample
,然后在
DerivedSample
中提供一个构造函数来复制必要的属性。这样,您可以保持与以前的对象的向后兼容性,但仍然可以使用较新的类

另一方面,WCF序列化处理了许多对象版本控制问题。如果项目需要与对象版本控制进行向后/向前兼容,则可以考虑切换到使用DATACONTRATS。
-Doug

从这个问题来看,失败的是尝试将序列化的DerivedSample读入具有旧版本程序集的应用程序中——因此没有DerivedSample类,只有Sample类

我认为这是行不通的,因为序列化的类(DerivedSample)在反序列化应用程序中根本不存在任何形式

当类本身进行版本控制而不是使用继承时,序列化似乎工作得最好。所以您需要修改Sample以添加新属性,而不是从中派生。新字段应标记为可选(提供向后兼容性),在反序列化为旧版本(提供向前兼容性)时忽略无关字段:

这是你的选择吗?

这是新作品还是现有作品<代码> BinaryFormatter < /代码>对于这样的事情非常敏感,但是如果你想要二进制输出,你可能需要考虑类似于ToeBuffnet的东西,它使用更可预测的基于契约的输出;这意味着,无论您是否更改特定类型,您都可以将数据返回到应用程序中

如果二进制不重要,你也可以考虑XML;code>XmlSerializer,

DataContractSerializer
,等等。在我看来,
BinaryFormatter
不应用于在最短时间以外的任何时间内保存数据


您强调前向/后向兼容性很重要;在这种情况下,我强烈建议您使用
BinaryFormatter
来解决这个问题。

您需要使用所谓的序列化代理。您可以将其注入二进制序列化程序,然后在运行时代理可以将正在序列化/反序列化的内容替换为您自己的类型。在过去,当类型在程序集之间移动并且代码不再能够反序列化旧文件时,我使用了它。有关代理的更多信息,请参见:

实际上没有,因为现在我们有两种不同类型的文件样本类型和DerivedSample类型。我们需要分别处理这两个问题。但可能我会使用可选字段和枚举来维护类型。嗨,Doug,就像我说的fwd兼容性不是问题,因为在反序列化文件时,我使用了基类的引用。所以,若一个文件包含Sample的对象,它将被正常反序列化。如果它包含DerivedSample obj,它仍然会被正常反序列化,如果我需要访问新属性,就必须将其类型转换为DerivedSample。谢谢你的回复,兄弟。。。但非常不幸的是,我被迫使用BinaryFormatter,因为我使用的第三方dll需要二进制输入。要指定的字节数组。现在我必须接受它,并且必须让老板相信,已经实现了backword兼容性,无法实现前向兼容性。我能提供的最佳解决方案是,应用程序将优雅地退出@二进制和二进制是没有问题的;protobuf net是一个二进制序列化程序;它不是二进制格式化程序-p当然,如果已经太晚了,那也没用。也许下次吧。基本上,所有序列化程序都可以被视为二进制。而且大多数可以(以某种方式)被视为文本。
[Serializable]
public class Sample
{
    String someString;
    int someInt;

    public Sample()
    {
    }

    public Sample(String _someString, int _someInt)
    {
        this.someInt = _someInt;
        this.someString = _someString;
    }

    public String SomeString
    {
        get { return someString; }
    }

    public int SomeInt
    {
        get { return someInt; }
    }
}

[Serializable]
public class DerivedSample : Sample
{
    String someMoreString;
    int someMoreInt;

    public DerivedSample ()
        : base()
    {
    }

    public DerivedSample (String _someString, int _someInt, String _someMoreString, int _someMoreInt)
        :
        base(_someString, _someInt)
    {
        this.someMoreString = _someMoreString;
        this.someMoreInt = _someMoreInt;
    }
    public String SomeMoreString
    {
        get { return someMoreString; }
    }

    public int SomeMoreInt
    {
        get { return someMoreInt; }
    }
}