属性的 DataContractSerializer 反序列化从派生类移动到基类
本文关键字:移动 基类 派生 DataContractSerializer 反序列化 属性 | 更新日期: 2023-09-27 18:33:44
使用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 反序列化(反序列化后属性为 null)。我说的是属性,前面有a:(在这种情况下是位置和开放时间)。
我们有很多这样的文件保存数据。我可以使用哪些选项正确反序列化这些文件?
请注意,[已知类型] 属性在 Base 和 Child 类上使用
将属性移动到基类时,它们实际上移动到另一个 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>
我的解决方案是将属性移回原始类,并将它们保留在最初移动到的类中。它现在给出了Property hides the inherited member...Use the new keyword if hiding was intended
的警告,但我可以接受,因为反序列化现在再次工作,我们可以将数据从一个提供程序移动到另一个提供程序。我找不到任何其他解决方案,并且无法修改所有序列化数据文件。
正如上面或下面 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
通过反射读取属性,因此它并不真正关心属性是否私有,但将属性放在其原始位置的私有位置会阻止从代码中使用它(按预期)。