简体   繁体   English

二进制序列化和自动属性

[英]Binary serialization and automatic properties

I have a class like this: 我有一个这样的课:

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

public interface IBar
{
    //whatever
}

The class is used for binary serialization (standard use of BinaryFormatter). 该类用于二进制序列化(标准使用BinaryFormatter)。 An implementation of IBar is marked with [Serializable] so everything works. IBar的实现标有[Serializable],所以一切正常。

Now I want not to serialize Bar and preserve backwards compatibility (it was not referenced in the code anyway). 现在我不想序列化Bar并保留向后兼容性(无论如何都没有在代码中引用)。 NonSerialized attribute seems to be enough. NonSerialized属性似乎就足够了。 However it can be applied only to fields, not to automatic properties. 但是它只能应用于字段,而不能应用于自动属性。 So I tried this: 所以我尝试了这个:

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

Suprisingly it works well - I can both deserialize old Foos and the new ones. 令人惊讶的是它运作良好 - 我可以将旧的Foos和新的Foos反序列化。

My question is: how can it possibly work if these are the fields that are serialized and the automatic property's backing field is likely to have some non-C# characters in its name? 我的问题是:如果这些是序列化的字段并且自动属性的支持字段可能在其名称中包含一些非C#字符,它怎么可能有效呢?

In other words: 换一种说法:

Old Foo's IBar field name (my guess): k__BackingField Old Foo的IBar字段名称(我猜):k__BackingField

New Foo's IBar field name: _bar New Foo的IBar字段名称:_bar

Obviously they don't match, so how BinaryFormatter overcomes this? 显然它们不匹配,所以BinaryFormatter如何克服这个问题?

I think there is something strange in your example. 我认为你的例子中有一些奇怪的东西。 BinaryFormatter shouldn't be able to handle this (as far as I know, unless this is changed in 4.5 which I doubt), which is why it is quite dangerous to use if backwards compatibility is necessary. BinaryFormatter不应该能够处理这个问题(据我所知,除非我在4.5中对此进行了更改),这就是为什么如果需要向后兼容性则使用它是非常危险的。 Are you sure the value is serialized from the old version and deserialized to the new version? 您确定该值是从旧版本序列化并反序列化为新版本吗? Can you verify that the deserialized data matches, and aren't null? 你能验证反序列化的数据是否匹配,并且不是空的?

For a complete example of a program that verifies that it does not work, see here. 对于验证它工作程序的完整的例子,在这里看到。 http://www.infragistics.com/community/blogs/josh_smith/archive/2008/02/05/automatic-properties-and-the-binaryformatter.aspx http://www.infragistics.com/community/blogs/josh_smith/archive/2008/02/05/automatic-properties-and-the-binaryformatter.aspx

You will not see any exceptions, but the old value from the field named xyz__backingfield will be lost, and replaced in the new class by a default value. 您将看不到任何异常,但名为xyz__backingfield的字段中的旧值将丢失,并在新类中被默认值替换。

If you want to be backwards compatible, avoid using automatic properties, or you will be in a world of trouble very soon. 如果您想要向后兼容,请避免使用自动属性,否则您很快就会遇到麻烦。 In fact it doesn't really matter, since the BinaryFormatter in default (automatic) mode is only really useful if you want to serialize objects and deserialize them again in the same application, for example for copy & paste or a similar operation. 实际上它并不重要,因为默认(自动)模式下的BinaryFormatter仅在您想要序列化对象并在同一应用程序中再次反序列化它们时才真正有用,例如复制和粘贴或类似操作。 In that case you have no versioning issues since it will be the same code doing both the serialization and deserialization. 在这种情况下,您没有版本控制问题,因为序列化和反序列化都是相同的代码。

To make serialization backwards compatible without losing your mind, make sure you have full control of the schema. 要使序列化向后兼容而不会失去理智,请确保您完全控制架构。 Good examples of serializers where you have a decent chance of staying out of trouble are DataContractSerializer, Json.NET or Protocol buffers (for example protobuf-net). 你有很大机会避免麻烦的序列化器的好例子是DataContractSerializer,Json.NET或Protocol缓冲区(例如protobuf-net)。

As a last possibility you can implement ISerializable and use the dictionary storage of BinaryFormatter, but then you have all the drawbacks of hand-rolling your serialization anyway. 作为最后一种可能性,您可以实现ISerializable并使用BinaryFormatter的字典存储,但是无论如何您都有手动滚动序列化的所有缺点。

On a sidenote if you want to apply attributes to a backing field try [field:AttriuteType] which is useful to mark backing fields of events as non serialized for example . 在旁注中,如果要将属性应用于后备字段,请尝试[field:AttriuteType],这对于将事件的后备字段标记为非序列化非常有用。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM