具有继承更改的数据协定

本文关键字:数据 继承 | 更新日期: 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,并保留新版本和旧版本,如果您希望随着合同的发展向后兼容。