由于缺乏远见,我使用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中也看不到可以匹配的order值。)
除了编写一些代码来加载xml并插入缺少的节点之外,是否还有其他选择?(或者等价地设置一个并行类型,然后从一个类型反序列化,然后重新序列化到另一个类型?)如果不是,我可能只需要加载当前类型并反序列化为JsonNet或protobuf,但是我是否错过了DataMember/等更直接的东西呢?
发布于 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对自动实现的属性的秘密支持字段执行此操作
[Serializable]
public class InheritedClass : BaseClass
{
public string StringId { get; set; }
[field: OptionalField]
public int IntId { get; set; }
} 在c# 7.3之前,无法将属性应用于自动实现的属性的支持字段。因此,您需要使支持字段显式,并向其添加属性:
[Serializable]
public class InheritedClass : BaseClass
{
public string StringId { get; set; }
[OptionalField]
int intId;
public int IntId { get { return intId; } set { intId = value; } }
} 备注:
NetDataContractSerializer将优先使用这些类型,而不是默认的[Serializable]约定,并允许您显式地指示要序列化的属性(并提供比秘密支持字段名更清晰的名称)。不幸的是,将数据协定属性添加到遗留类型并不总是实用的。
NetDataContractSerializer has not been ported to .NET Core / .NET 5和可能的never will be.https://stackoverflow.com/questions/33813551
复制相似问题