【问题标题】:DataContractSerializer deserialization of properties moved from derived class to base classDataContractSerializer 属性的反序列化从派生类移动到基类
【发布时间】:2012-05-10 20:39:21
【问题描述】:

使用 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 类中都使用

【问题讨论】:

    标签: c# .net datacontractserializer


    【解决方案1】:

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

    <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>
    

    【讨论】:

    • 谢谢,这是显而易见的答案,但需要手动更改 XML 文件。您是否知道另一种方法可以使 DCS 在 Base 类中找到这些属性并对其进行序列化?
    • @mare 这两个选项都在这个答案中;使用 Namespace 属性将旧的命名空间添加到新的 DataContract,或者更改 xml 中指定的命名空间。
    【解决方案2】:

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

    【讨论】:

    • 希望你看看我的回答...我想它可以帮助你摆脱困境。
    【解决方案3】:

    正如上面或下面的 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 通过反射读取属性,因此它并不真正关心该属性是私有的,但在其原始位置私有的属性会阻止代码使用它(如预期的那样)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多