1

我正在使用 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;
}

但我得到 name = null。我知道这取决于顺序:文件先用年龄保存,然后从名称开始读取,因为它在基类上。
有没有办法处理这个问题,也许通过改变顺序?

4

2 回答 2

3

我不认为这是可能的。

过去的 xml 本来是

<dog>
    <name>Bob</name>
    <age>10</age>
</dog>

它现在期待

<animal>
    <name>Bob</name>
    <dog>
        <age>10</age>
    </dog>
</animal>

在新 DataContract 上序列化的任何内容中,该属性都更高。更改继承层次结构是该IExtensibleDataObject方法的重大更改。

允许将继承与数据合同一起使用,前提是继承不用作版本控制机制并且遵循某些规则。如果某个类型派生自某个基类型,则不要让它在未来版本中派生自不同的基类型(除非它具有相同的数据协定)。对此有一个例外:您可以将类型插入到数据协定类型与其基类型之间的层次结构中,但前提是它不包含与其他类型的任何可能版本中的其他成员同名的数据成员。层次结构。通常,在同一继承层次结构的不同级别使用具有相同名称的数据成员会导致严重的版本控制问题,应该避免。

最佳实践中的更多内容:数据合同版本控制

编辑1:

您也许可以尝试在 Animal 中将 Name 设为虚拟并在 Dog 中覆盖它?或者一些疯狂的方法来强制序列化的新版本在狗下命名。即类似的东西,

[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; 
} 
于 2012-05-30T15:23:59.480 回答
1

您应该查看此 SO 帖子中讨论的 WCF 合同版本控制

Namespace本质上,如果您希望随着合同的发展而向后兼容,则需要在您的设备上分配 aServiceContract并保留新旧版本。

于 2012-05-30T15:27:11.630 回答