我有这样一个类:
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# 字符,它怎么可能工作?
换句话说:
Old Foo 的 IBar 字段名(我猜的):k__BackingField
新建Foo的IBar字段名:_bar
显然它们不匹配,那么 BinaryFormatter 如何克服这个问题呢?
最佳答案
我认为你的例子有些奇怪。 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 或 Protocol buffers(例如 protobuf-net)是您很有可能避免麻烦的序列化程序的好例子。
作为最后一种可能性,您可以实现 ISerializable 并使用 BinaryFormatter 的字典存储,但是无论如何您都会遇到手动序列化的所有缺点。
在旁注中,如果您想将属性应用于支持字段,请尝试 [field:AttriuteType],这对于将事件的支持字段标记为非序列化非常有用。
关于c# - 二进制序列化和自动属性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15133298/