首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >具有新属性的NetDataContractSerializer反序列化

具有新属性的NetDataContractSerializer反序列化
EN

Stack Overflow用户
提问于 2015-11-20 04:16:04
回答 1查看 489关注 0票数 3

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

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

代码语言:javascript
复制
[Serializable]
public class InheritedClass : BaseClass
{
    public string StringId { get; set; }
}

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

代码语言:javascript
复制
[Serializable]
public class InheritedClass : BaseClass
{
    public string StringId { get; set; }
    public int IntId { get; set; }
}

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

代码语言:javascript
复制
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属性来解决这个问题,比如:

代码语言:javascript
复制
[DataMember(IsRequired = false)]

然后,问题是切换到DataMember (正如我应该预先做的那样,或者使用不同的序列化程序)改变了隐式的字母顺序,然后我的大多数字段将不会像众所周知的那样进行反序列化。

我尝试手动添加一个与磁盘上的排序一致的排序(通过属性上的Order属性),但似乎也没有考虑到这一点。(我在原始xml中也看不到可以匹配的order值。)

除了编写一些代码来加载xml并插入缺少的节点之外,是否还有其他选择?(或者等价地设置一个并行类型,然后从一个类型反序列化,然后重新序列化到另一个类型?)如果不是,我可能只需要加载当前类型并反序列化为JsonNet或protobuf,但是我是否错过了DataMember/等更直接的东西呢?

EN

回答 1

Stack Overflow用户

发布于 2015-11-20 07:34:23

[Serializable]标记类型意味着可以通过序列化它的来序列化该类型,而不是序列化它的属性。当存在此属性时,NetDataContractSerializer会遵守此属性,并按指示序列化字段。对于auto-implemented property,秘密后备字段是实际序列化的字段。

在添加新字段时,处理遗留数据的一般做法是用[[OptionalField]](https://msdn.microsoft.com/en-us/library/system.runtime.serialization.optionalfieldattribute(v=vs.110%29.aspx)标记它,以表明它不会总是出现在序列化流中。在c# 7.3和更高版本中,可以使用field-targeted attribute对自动实现的属性的秘密支持字段执行此操作

代码语言:javascript
复制
[Serializable]
public class InheritedClass : BaseClass
{
    public string StringId { get; set; }

    [field: OptionalField]
    public int IntId { get; set; }
}    

在c# 7.3之前,无法将属性应用于自动实现的属性的支持字段。因此,您需要使支持字段显式,并向其添加属性:

代码语言:javascript
复制
[Serializable]
public class InheritedClass : BaseClass
{
    public string StringId { get; set; }

    [OptionalField]
    int intId;

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

备注:

  • 正如问题中提到的,如果一个类型被标记为data contract attributes,那么NetDataContractSerializer将优先使用这些类型,而不是默认的[Serializable]约定,并允许您显式地指示要序列化的属性(并提供比秘密支持字段名更清晰的名称)。

不幸的是,将数据协定属性添加到遗留类型并不总是实用的。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/33813551

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档