3

我有这样一类:二进制序列和自动属性

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

public interface IBar 
{ 
    //whatever 
} 

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

现在我想不要序列化栏和保留向后兼容性(它没有在代码中引用)。 NonSerialized属性似乎够用了。但是,它只能应用于字段,而不能应用于自动属性。所以我试过这个:

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

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

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

换句话说:

老Foo的伊巴尔字段名(我猜测):k__BackingField

新富的伊巴尔字段名称:_bar

显然它们不匹配,所以如何BinaryFormatter的克服了这一?

+0

当你说该属性从未在代码中引用并不意味着它总是'null'?如果是这样的话,为什么它可以反序列化整个二进制不兼容性的答案是,它实际上从来不需要。 – JRoughan 2013-02-28 11:06:15

+0

我不够精确。该属性在构造函数中被分配了一个值。它从未在其他地方引用过。坦率地说,它应该从Foo中删除。 – dzendras 2013-02-28 12:08:01

+0

您的“旧”代码在语法上是错误的 - 请指定属性名称,因为它几乎肯定会影响行为。 – 2017-05-31 15:23:54

回答

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在默认(自动)模式下才非常有用。在这种情况下,你不会有任何版本问题,因为它将是同时执行序列化和反序列化的代码。

要使序列化向后兼容而不会失去主意,请确保完全控制架构。 DataContractSerializer,Json.NET或协议缓冲区(例如protobuf-net)可以很好地避免麻烦。

作为最后的可能性,您可以实现ISerializable并使用BinaryFormatter的字典存储,但是您仍然有手动滚动序列化的所有缺点。

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

+0

谢谢你的回应。不幸的是切换到任何其他序列化器已经太晚了。我必须使用BinaryFormatter来制定解决方法,并且有时间(将来)完全摆脱BinarySerialization。 – dzendras 2013-02-28 13:10:34