二进制序列化和自动属性

时间:2013-02-28 10:38:24

标签: c# deserialization .net-4.5 binaryformatter binary-serialization

我有一个这样的课程:

public class Foo
{
    public IBar {get;set;}
    //tons of other properties
}

public interface IBar
{
    //whatever
}

该类用于二进制序列化(标准使用BinaryFormatter)。 IBar的实现标有[Serializable],所以一切正常。

现在我不想序列化Bar并保留向后兼容性(无论如何都没有在代码中引用它)。 NonSerialized属性似乎已经足够了。但是它只能应用于字段,而不能应用于自动属性。所以我尝试了这个:

public class Foo
{
    private IBar _bar;
    [NonSerializable]
    public IBar Bar 
    {
        get { return _bar; }
        set { _bar = value; }
    }
}

令人惊讶的是它运作良好 - 我可以对旧的Foos和新的Foos进行反序列化。

我的问题是:如果这些是序列化的字段并且自动属性的支持字段可能在其名称中包含一些非C#字符,它怎么可能有效呢?

换句话说:

Old Foo的IBar字段名称(我猜):k__BackingField

New Foo的IBar字段名称:_bar

显然他们不匹配,所以BinaryFormatter如何克服这个问题?

1 个答案:

答案 0 :(得分:1)

我认为你的例子中有一些奇怪的东西。 BinaryFormatter不应该能够处理这个问题(据我所知,除非我在4.5中对此进行了更改),这就是为什么如果需要向后兼容性则使用它是非常危险的。您确定该值是从旧版本序列化并反序列化为新版本吗?你能验证反序列化的数据是否匹配,并且不是null?

有关验证工作的程序的完整示例,请参阅此处。 http://www.infragistics.com/community/blogs/josh_smith/archive/2008/02/05/automatic-properties-and-the-binaryformatter.aspx

您不会看到任何异常,但是名为xyz__backingfield的字段中的旧值将丢失,并在新类中被默认值替换。

如果您想要向后兼容,请避免使用自动属性,否则您很快就会遇到麻烦。实际上它并不重要,因为默认(自动)模式下的BinaryFormatter仅在您想要序列化对象并在同一应用程序中再次反序列化它们时才真正有用,例如对于copy&粘贴或类似的操作。在这种情况下,您没有版本控制问题,因为序列化和反序列化都是相同的代码。

要使序列化向后兼容而不会失去理智,请确保您可以完全控制架构。你有很好的机会避免麻烦的序列化程序的好例子是DataContractSerializer,Json.NET或Protocol缓冲区(例如protobuf-net)。

作为最后一种可能性,您可以实现ISerializable并使用BinaryFormatter的字典存储,但是无论如何您都有手动滚动序列化的所有缺点。

在旁注中,如果要将属性应用于支持字段,请尝试[field:AttriuteType],这对于将事件的支持字段标记为非序列化非常有用。