具有继承更改的数据协定
本文关键字:数据 继承 | 更新日期: 2023-09-27 18:35:41
我正在使用DataContracts来序列化对象。假设我序列化了一个以这种方式结构化的数据:
[DataContract]
public class Dog : IExtensibleDataObject
{
[DataMember]
public int age;
[DataMember]
public string name;
ExtensionDataObject IExtensibleDataObject.ExtensionData { get; set; }
}
现在我正在更改我的体系结构,我想使用以下类读取以前序列化的数据:
[DataContract]
[KnownType(typeof(Dog))]
public class Animal : IExtensibleDataObject
{
[DataMember]
public string name;
ExtensionDataObject IExtensibleDataObject.ExtensionData { get; set; }
}
[DataContract]
public class Dog : Animal
{
[DataMember]
public int age;
}
但我获得名称 = 空。我知道这取决于顺序:文件首先保存为年龄,然后从名称开始读取,因为它在基类上。
有没有办法解决这个问题,也许通过更改顺序?
我认为这是不可能的。
过去的 xml 应该是
<dog>
<name>Bob</name>
<age>10</age>
</dog>
它现在期待
<animal>
<name>Bob</name>
<dog>
<age>10</age>
</dog>
</animal>
该属性在新数据协定上序列化的任何内容中都位于较高位置。更改继承层次结构是 IExtensibleDataObject
方法的重大更改。
允许将继承与数据协定一起使用, 前提是继承不用作版本控制机制,并且 遵循某些规则。如果类型派生自某个基数 类型,将来不要让它从不同的基类型派生 版本(除非它具有相同的数据协定)。有一个例外 为此:您可以将类型插入到数据之间的层次结构中 协定类型及其基本类型,但前提是它不包含数据 在任何可能的版本中与其他成员同名的成员 层次结构中的其他类型的类型。通常,使用数据成员 在同一继承的不同级别具有相同的名称 层次结构可能导致严重的版本控制问题,应该 避免。
有关最佳实践的更多信息:数据协定版本控制
编辑 1:
您也许可以尝试在动物中将名称设为虚拟并在狗中覆盖它? 或者一些疯狂的方法强制序列化的新版本在狗下有名字。即类似的东西,
[DataContract]
[KnownType(typeof(Dog))]
public class Animal : IExtensibleDataObject
{
public virtual string name;
ExtensionDataObject IExtensibleDataObject.ExtensionData { get; set; }
}
[DataContract]
public class Dog : Animal
{
[DataMember]
public override string name;
[DataMember]
public int age;
}
您应该看看这篇 SO 文章中讨论的 WCF 协定版本控制。
从本质上讲,您需要在ServiceContract
上分配一个Namespace
,并保留新版本和旧版本,如果您希望随着合同的发展向后兼容。