【问题标题】:Can extracting a base class break binary serialisation可以提取基类中断二进制序列化
【发布时间】:2018-10-25 21:16:49
【问题描述】:

如果我有一个包含多个字段的类,并且我使用二进制序列化对其进行序列化。

然后我提取一个基类并将该类中的一些字段移动到基类中。例如。

class Class
{
     int field1;
     string field2;
}

改为

class Class : BaseClass
{
     int field1;
}

class BaseClass
{
     string field2;
}

这是否有可能以任何方式破坏序列化 - 即是否总是可以将旧版本的 Class 反序列化为新版本的 Class,反之亦然。

我进行的实验表明这很好,但如果有人知道这不起作用的任何边缘情况,那么在我将它放入生产代码之前那显然会很好。

【问题讨论】:

  • BinaryFormatter

标签: c# .net binary-serialization


【解决方案1】:

编辑: 反序列化时出现问题:成员“field1”将无法正确反序列化。

1) 序列化人:

var person = new Employee()
            { 
                Name = "Mark Zuckerberg",
                Salary = 1000
            };

var bf = new BinaryFormatter();
bf.Serialize(new FileStream("C:\\TEMP\\test.dat", FileMode.Create), person);


[Serializable]
public class Employee
{
  public string Name { get; set; }
  public decimal Salary { get; set; }
}

2) 改变了类结构

[Serializable]
public abstract class Person
{
  public string Name { get; set; }           
}

[Serializable]
public class Employee : Person
{            
  public decimal Salary { get; set; }
}

3) 反序列化:名称为空


原答案:

假设您使用的是BinaryFormatterthis 文章没有提及任何相关内容,所以我没关系(编辑:没关系)。

以下是一些普遍遵循的最佳实践(也摘自上述文章):

  • 切勿删除序列化字段。
  • 永远不要将 NonSerializedAttribute 属性应用于字段,如果 属性未应用于先前版本中的字段。
  • 切勿更改序列化字段的名称或类型。
  • 添加新的序列化字段时,应用 OptionalFieldAttribute 属性。
  • 从字段中删除 NonSerializedAttribute 属性时(即 在以前的版本中不可序列化),应用 可选FieldAttribute 属性。
  • 对于所有可选字段,使用 序列化回调,除非 0 或 null 作为默认值是可接受的。

为确保类型与未来的序列化引擎兼容,请遵循以下准则:

  • 始终在 OptionalFieldAttribute 上设置 VersionAdded 属性 属性正确。
  • 避免分支版本控制。

【讨论】:

  • 嗯。你能想出什么办法来解决这个问题吗?
  • @YairHalberstadt 恐怕不是一个合适的解决方案。我想到的显而易见的选择是维护旧模型,直到数据被迁移然后丢弃它。在您的反序列化代码中,您可以检查 Name 是否为空,使用旧模型进行反序列化,然后将该对象分配给新的一。
猜你喜欢
  • 2021-12-03
  • 1970-01-01
  • 2014-08-02
  • 1970-01-01
  • 2011-09-26
  • 2016-08-16
  • 1970-01-01
  • 2014-01-04
  • 2017-01-08
相关资源
最近更新 更多