3

我有这样的课:

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 和新的。

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

换句话说:

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

新 Foo 的 IBar 字段名称:_bar

显然它们不匹配,那么 BinaryFormatter 如何克服这个问题?

4

1 回答 1

1

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

有关验证其不工作的程序的完整示例请参见此处。 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 的字典存储,但是无论如何您都会遇到手动滚动序列化的所有缺点。

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

于 2013-02-28T12:20:26.480 回答