1

使用 DCS,我试图从 XML 中反序列化对象,其中序列化的对象是 Child 继承类 Base 的类型,其中 Child 具有一些已反序列化但后来在代码中移动到类 Base 的属性。现在这些属性不会被反序列化:

看看这个 XML:

<Base i:type="a:DirectoryEntry" xmlns="http://schemas.datacontract.org/2004/07/pending.Core.Models" xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns:a="http://schemas.datacontract.org/2004/07/pending.Core.Models.Directory">
    <Active>true</Active>
    <ContentType>DirectoryEntry</ContentType>
    <Created>2012-03-12T11:51:25.3401552+01:00</Created>
    <a:Location>location</a:Location>
    <a:OpenHours>opening</a:OpenHours>
</Base>

xmlns:a 表示派生类型名称。这个类用来存放那些道具。现在它们被移到基类中,不再被 DCS 反序列化(反序列化后属性为空)。我说的是属性:在它们前面(在这种情况下是位置和开放时间)。

我们有很多这样的文件保存数据。使用 DCS 正确反序列化这些文件有哪些选择?

请注意 [KnownType] 属性在 Base 和 Child 类中都使用

4

3 回答 3

1

当您将属性移至基类时,它们实际上已移至另一个 XML 名称空间。基类可能定义在 namespace pending.Core.Models,而派生类定义在pending.Core.Models.Directory(我假设您没有在Namespace属性的[DataContract]属性中指定任何内容。因此,如果您更改了元素应该在的命名空间,那么序列化程序将'无法将它与您拥有的数据匹配。如果您将最后两个属性移至基类,则需要更改 XML 元素的命名空间LocationOpenHours.

<Base i:type="a:DirectoryEntry"
      xmlns="http://schemas.datacontract.org/2004/07/pending.Core.Models"
      xmlns:i="http://www.w3.org/2001/XMLSchema-instance"
      xmlns:a="http://schemas.datacontract.org/2004/07/pending.Core.Models.Directory">
  <Active>true</Active>
  <ContentType>DirectoryEntry</ContentType>
  <Created>2012-03-12T11:51:25.3401552+01:00</Created>
  <Location>location</Location>
  <OpenHours>opening</OpenHours>
</Base>
于 2012-05-10T22:33:33.727 回答
0

我的解决方案是将属性移回原始类,并将它们留在它们首先移动到的类中。它现在给出了警告,Property hides the inherited member...Use the new keyword if hiding was intended但我可以忍受,因为反序列化现在再次起作用,我们可以将数据从一个提供者移动到另一个提供者。我找不到任何其他解决方案,并且无法修改所有序列化数据文件。

于 2012-05-14T17:37:35.523 回答
0

正如 mare 上面或下面所提到的,在接受的答案中,没有原始类中没有该属性的解决方案。但是,通过new在原始类的属性声明中使用关键字,可以禁用警告。我还得到了以下结构:

[DataContract]
class Base
{
    [DataMember]
    public int X { get; set; }
} 

[DataContract]
class Derived : Base
{
    [DataMember]
    private new int X
    {
        get => base.X;
        set => base.X = value;
    }
}

通过DataContractSerializer反射读取属性,因此它并不真正关心该属性是私有的,而是将属性放在其原始位置私有,从而防止从代码中使用它(如预期的那样)。

于 2019-05-14T13:21:32.987 回答