NetDataContractSerializer使用新属性进行反序列化

时间:2015-11-19 20:16:04

标签: c# xml serialization netdatacontractserializer

缺乏任何真正的远见,我已经使用NetDataContractSerializer序列化了仅使用Serializable修饰的大量数据,现在我想添加一个新字段。我有什么选择?

原始类看起来像这样(具有几个级别的继承和相当多的字段):

[Serializable]
public class InheritedClass : BaseClass
{
    public string StringId { get; set; }
}

现在我想添加另一个属性,比如说:

[Serializable]
public class InheritedClass : BaseClass
{
    public string StringId { get; set; }
    public int IntId { get; set; }
}

现在,当我更新类并进行反序列化时,我收到一个异常,因为新字段不存在,如:

Exception thrown: 'System.Runtime.Serialization.SerializationException' in System.Runtime.Serialization.dll

Additional information: Error in line 1 position 601. 'Element' '_x003C_StringId_x003E_k__BackingField' from namespace 'http://schemas.datacontract.org/2004/07/QT' is not expected. Expecting element '_x003C_IntId_x003E_k__BackingField'.

好的,所以这是有道理的,因为NetDataContractSerializer需要相同的类。我可以使用DataMember属性来解决这个问题:

[DataMember(IsRequired = false)]

然后问题是切换到DataMember(因为我应该事先做,或者使用不同的序列化程序)会改变隐式字母顺序,然后我的大多数字段将默默地不反序列化,这是众所周知的。

我尝试手动添加与磁盘上的订购一致的订购(通过属性上的Order属性),但这似乎不受尊重。 (我没有看到我可以在原始xml中匹配的订单值。)

除了编写加载xml并插入缺少的节点之外还有其他选择吗? (或等效地设置一个并行类型并从一个重新序列化反序列化到另一个?)如果没有,我可能只是加载当前类型并反序列化为JsonNet或protobuf,但我错过了任何更直接的东西数据成员的/ etc?

1 个答案:

答案 0 :(得分:2)

使用[Serializable]标记类型意味着应该通过序列化其公共和私有字段来序列化该类型 - 而不是其属性。添加新字段时,通常用来处理遗留数据的是用[OptionalField]标记它以表明它不会总是出现在序列化流中 - 但是一个不能做具有自动实现的属性,因为无法访问秘密支持字段。

解决方案是显式实现所有新属性,并使用必需属性标记支持字段:

[Serializable]
public class InheritedClass : BaseClass
{
    public string StringId { get; set; }

    [OptionalField]
    int intId;

    public int IntId { get { return intId; } set { intId = value; } }
}