【问题标题】:Renaming fields then deserializing in C#重命名字段然后在 C# 中反序列化
【发布时间】:2009-06-02 22:58:23
【问题描述】:

我将数据存储在已使用 .net BinaryFormatter 序列化的类的实例中。我现在想重命名类中的一个字段,但仍然能够反序列化旧数据。

一种选择是实现 ISerializable 并手动反序列化类的所有字段。但这似乎需要做很多工作,尤其是如果我的班级有很多字段并且我只重命名了一个字段。

有没有更好的办法?


Craig 建议保留旧类的副本以进行反序列化,并将值复制到新类。我在其他地方也看到过这个建议——这比实现 ISerializable 有什么优势?据我所见,复制该类给我留下了该类的 2 个几乎相同的副本,而且我仍然必须将旧类中的所有值复制到新类中——这似乎与使用 ISerializable 实现相同的工作量几乎重复的类被扔进了混合中。


两个答案都提到了Binders。我已经成功地使用了 SerializationBinder 来反序列化一个被序列化为类 Foo 的类 Bar,但那是因为类的名称发生了变化。当您重命名字段时,SerializationBinder 是否也有帮助 - 比如当 int m_Left 已重命名为 int m_Right 时?

【问题讨论】:

  • 在 Binder 的 BindToType 方法中,当您获得具有目标类型(类)的 typeName 字符串时,只需返回您更改属性的新类型。类只改变了属性,但现在是不同的类型。没有办法只适用于一个属性。

标签: c# serialization


【解决方案1】:

是的,这是基于字段的序列化程序的问题。您可以使用自定义 Binder 或“序列化代理”来避免实现 ISerializable,但这只是逐个解决方案。

我已经讨论过这个话题(在混淆器和自动道具的背景下)here。我的建议是:不要使用 BinaryFormatter 在版本之间保持数据的持久性......为此,请查看基于合约的序列化程序:

  • XmlSerializer
  • DataContractSerializer
  • 或二进制,如protobuf-net

这些对你今天都没有帮助,但它可能会帮助你在未来围绕它进行设计。

【讨论】:

    【解决方案2】:

    您可以尝试让旧课程仅出于补液的目的而闲逛,然后将您需要的字段复制到新课程。仍然有点痛苦,但应该可以工作。

    【讨论】:

      【解决方案3】:

      我之前为此使用了 SerializationBinder 类

      http://msdn.microsoft.com/en-us/library/system.runtime.serialization.serializationbinder.aspx

      它可用于反序列化,因此您可以将旧类型重新映射到新类型。

      【讨论】:

        【解决方案4】:

        如果您只是将该属性上的访问修饰符更改为私有,然后拥有一个具有新名称的公共属性,该新名称基本上包装了旧名称。这样,您仍然应该能够反序列化(我认为),但是使用此类的任何人都不知道旧名称。只是一个想法......

        【讨论】:

        • 如果序列化作用于属性,那将起作用,但据我所知,它直接使用私有字段......(如果我在记事本中打开文件,我会看到字段像 m_Foo 和 m_Bar 这样的名称,而不是像 Foo 和 Bar 这样的属性名称...
        猜你喜欢
        • 1970-01-01
        • 2010-10-18
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多