【问题标题】:Problems deserializing class after newly added member新添加成员后反序列化类的问题
【发布时间】:2016-02-05 22:08:34
【问题描述】:

我有一个简单的“可序列化”类,定义如下:

[Serializable]
public class LayoutDetails
{       
    public bool IsRefreshEnabled { get; set; }

    public string GridSettings { get; set; }

    public List<string> GroupByPropertyNames { get; set; }
}

该类已使用以下例程进行序列化:

using (var memoryStream = new MemoryStream())
{
   var dc = new DataContractSerializer(obj.GetType());
   dc.WriteObject(memoryStream, obj);

   memoryStream.Flush();

   memoryStream.Position = 0;
   StreamReader reader = new StreamReader(memoryStream);
   serializedObject = reader.ReadToEnd();
}

我正在尝试使用以下例程对其进行反序列化:

   var bytes = new UTF8Encoding().GetBytes(serializedObject);
   using (var stream = new MemoryStream(bytes ))
   {
      var serializer = new DataContractSerializer(type);
      var reader = XmlDictionaryReader.CreateTextReader(stream, XmlDictionaryReaderQuotas.Max);
      obj = serializer.ReadObject(reader, true);
   }

效果很好;但是,现在,我想向该类添加一个新属性 (public int? Offset { get; set; })。当我将此属性添加到类并尝试反序列化以前序列化的实例(没有该属性)时,我得到一个异常:

Error in line 1 position 148. 'EndElement' 'LayoutDetails' from namespace 'http://schemas.datacontract.org/2004/07/WpfApplication1' is not expected. Expecting element '_x003C_Offset_x003E_k__BackingField'.

我的第一个想法是实现ISerializable 并使用反序列化ctor,所以我尝试了类似的方法,但它无法按名称找到任何成员 - 我尝试了几种组合...

public LayoutDetails(SerializationInfo info, StreamingContext context)
{
   this.IsRefreshEnabled = (bool)info.GetValue("_x003C_IsRefreshEnabled_x003E_k__BackingField", typeof(bool));
   this.IsRefreshEnabled = (bool)info.GetValue("_x003C_IsRefreshEnabled_x003E_k_", typeof(bool));
   this.IsRefreshEnabled = (bool)info.GetValue("_x003C_IsRefreshEnabled_x003E", typeof(bool));
   this.IsRefreshEnabled = (bool)info.GetValue("x003C_IsRefreshEnabled_x003E", typeof(bool));
   this.IsRefreshEnabled = (bool)info.GetValue("IsRefreshEnabled", typeof(bool));
}

使用 DataContractSerializer,如何在不破坏“旧”实例的反序列化的情况下向我的类添加新成员?

【问题讨论】:

  • 您正在使用reader.ReadToEnd() 读取任意二进制数据,这样做不是很安全。我不是 100% 确定这一点,但我认为你可以做的事情不会往返返回二进制数据。编辑:实际上是的,这完全行不通,您的序列化器正在使用UTF8Encoding,而您的解串器正在使用ASCIIEncoding。我很震惊它到目前为止工作。
  • 感谢有关编码不匹配的响应和良好的调用;我很惊讶它也能正常工作!尽管如此,在反序列化器中使用 UTF8 似乎并没有什么不同。

标签: c# .net wcf serialization


【解决方案1】:

您可以为新属性使用支持字段,并添加属性OptionalField

[Serializable]
public class LayoutDetails
{       
    [OptionalField]
    private int? offset;

    public bool IsRefreshEnabled { get; set; }

    public string GridSettings { get; set; }

    public List<string> GroupByPropertyNames { get; set; }

    public int? Offset
    {
        get { return offset; }
        set { offset = value; }
    }
}

如果你想设置一个默认值,你可以在类中添加一个带有OnDeserializing属性的方法:

[OnDeserializing]
private void SetOffsetDefault(StreamingContext sc)
{
    offset = 123;
}

【讨论】:

    猜你喜欢
    • 2013-04-08
    • 1970-01-01
    • 2022-08-21
    • 1970-01-01
    • 2020-10-12
    • 1970-01-01
    • 2019-05-28
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多