【问题标题】:DataContractSerializer does not deserialize collection of objectsDataContractSerializer 不反序列化对象集合
【发布时间】:2016-01-13 21:35:12
【问题描述】:

晚上好,我有以下 XML:

<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<project xmlns="">
  <title>MyProject</title>

  <nodes>
    <node>
      <name>base</name>
      <class>BaseNode</class>
    </node>

    <node>
      <name>detail</name>
      <class>DetailNode</class>
    </node>
    ...
  </nodes>
</project>

...我希望将其反序列化为以下对象结构,以便 Project 包含一个“标题”和一个 NodeCollection(其中又包含多个 Node 元素):

[DataContract(Name = "project")]
class Project
{
    [DataMember(Name = "title")]
    public string Title { get; set; }

    [DataMember(Name = "nodes")]
    public NodeCollection Nodes { get; set; }
}

[CollectionDataContract(Name = "nodes", ItemName = "node")]
class NodeCollection : List<Node>
{

}

[DataContract(Name = "node")]
class Node
{
    [DataMember(Name = "name")]
    public string Name { get; set; }

    [DataMember(Name = "class")]
    public string Class { get; set; }
}

使用此架构,反序列化完成时不会出错,返回预期的Project 对象,但是:

  • 项目“Title”已正确反序列化(其值为“MyProject”),
  • 项目“节点”不是(空的)。

Project 对象的 Title 属性设置为预期值,但 NodeCollection 始终为空。事实上,它甚至都没有初始化:

对象引用未设置为对象的实例

出于某种奇怪的原因,反序列化器“无法识别任何节点”。我尝试添加KnownType 属性,没有成功。

我做错了什么?

【问题讨论】:

    标签: c# xml serialization datacontract


    【解决方案1】:

    如果您指定NamespaceOrder 属性,它会起作用;否则它会抱怨意外的命名空间或无法完全读取节点,并且由于某种原因它期望 Title 出现在 Nodes 之后。

    [DataContract(Name = "project", Namespace="")]
    public class Project
    {
        [DataMember(Name = "title",Order=1)]
        public string Title { get; set; }
    
        [DataMember(Name = "nodes", Order=2)]
        public NodeCollection Nodes { get; set; }
    }
    
    [CollectionDataContract(Name = "nodes",Namespace="", ItemName = "node")]
    public class NodeCollection : List<Node> {  }
    
    [DataContract(Name = "node", Namespace="")]
    public class Node
    {
        [DataMember(Name = "name")]
        public string Name { get; set; }
    
        [DataMember(Name = "class")]
        public string Class { get; set; }
    }
    

    看着documentation

    数据排序的基本规则包括:

    • 如果数据协定类型是继承层次结构的一部分,则其基本类型的数据成员始终排在第一位。
    • 接下来是当前类型的不具有 DataMemberAttribute 属性集的 Order 属性的数据成员,按字母顺序排列。
    • 接下来是具有 DataMemberAttribute 属性集的 Order 属性的任何数据成员。它们首先按 Order 属性的值排序,然后如果某个 Order 值有多个成员,则按字母顺序排列。订单值可能会被跳过。

    因为“N”按字母顺序排在“T”之前,所以它期望NodeCollection 排在第一位。即使事情“乱七八糟”,它仍然会反序列化(这看起来很奇怪,但这就是它的工作原理)——它只会用 null 填充这些对象/成员。

    【讨论】:

    • 是的,谢谢,订购似乎可以解决问题。然而,这里有些奇怪。即使 XML 中的条目未按必要的顺序排列,排序也能解决问题。无论是title标签还是nodes,都无所谓,无论哪种方式都可以反序列化。这是为什么呢?
    • 同意这似乎很奇怪 - 来自 MSDN 文档的更新答案。请注意,即使它被反序列化,如果它的顺序不正确,Title 也会显示为null
    • 对,我在这里漏掉了一些东西。确实,排序很重要,否则这些值将未初始化。谢谢。
    • 另外,类型NodeCollection,只是为了作为一个集合,可以忽略。如果Project.NodesList&lt;Node&gt; 并且简单地被赋予DataMember(Name = "nodes") 属性,并且Node 类具有DataContract(Name = "node") 属性,则序列化/反序列化工作完美无缺。
    猜你喜欢
    • 2020-02-24
    • 1970-01-01
    • 2011-09-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多