首页 > 解决方案 > 反序列化对象忽略某些节点

问题描述

我有一个使用 XmlSerializer 序列化的对象。当试图将此 XML 文件反序列化回对象时,由于某种原因它正在跳过一个节点。

<?xml version="1.0" encoding="utf-8"?>
<Dialogue xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <Conversations>
    <Conversation Id="993fed92-6917-4003-975f-78df4ca77257" Name="sdfsf">
      <TextNode Id="8ce1fba9-9daf-4145-b374-d8d7df6ca983" IsGraphEntryPoint="false" NodePositionX="1056" NodePositionY="341">
        <Speaker>None</Speaker>
        <Lines />
      </TextNode>
      <ChoiceNode Id="7c697932-dbde-47a2-b931-bc881811ef63" IsGraphEntryPoint="false" NodePositionX="783" NodePositionY="605">
        <Choices>
          <ChoiceOptionNode ChoiceId="cbe28c44-a535-4191-80b2-1bb3d1881cb7" PortName="Choice#1" ConnectsTo="82fefda3-f6d9-4462-a39e-a20c56f97bcb">
            <Lines>
              <ChoiceOptionLineNode>
                <LanguageId>42d97432-c027-416d-2aa8-1ec47ca1410e</LanguageId>
                <LanguageCode>NL</LanguageCode>
                <Text />
              </ChoiceOptionLineNode>
            </Lines>
          </ChoiceOptionNode>
        </Choices>
      </ChoiceNode>
    </Conversation>
  </Conversations>
</Dialogue>

所有 Textnodes 都正确反序列化,但 Choicenodes 似乎完全被忽略了。

对象本身:

public class ChoiceNode : BaseConversationNode
    {
        [XmlArray("Choices")]
        [XmlArrayItem(ElementName = "ChoiceOptionNode")]
        public List<ChoiceOptionNode> Choices;
    }

public class ChoiceOptionNode
    {
        [XmlAttribute]
        public Guid ChoiceId;
        [XmlAttribute]
        public string PortName;
        [XmlArray("Lines")]
        [XmlArrayItem(ElementName = "ChoiceOptionLineNode")]
        public List<ChoiceOptionLineNode> Lines;
        [XmlAttribute]
        public Guid ConnectsTo;
    }

public class ChoiceOptionLineNode
    {
        public Guid LanguageId;
        public string LanguageCode;
        public string Text;
    }

public abstract class BaseConversationNode
    {
        [XmlElement(ElementName = "Connections")]
        public List<Output> Connections = new List<Output>();
        [XmlIgnore]
        public GraphNode Node;
        [XmlAttribute]
        public Guid Id;
        [XmlAttribute]
        public bool IsGraphEntryPoint;
        [XmlIgnore]
        public Rect NodeRect;
        [XmlAttribute]
        public float NodePositionX;
        [XmlAttribute]
        public float NodePositionY;
        /// <summary>
        /// The hex color of the node window
        /// </summary>
        /// <returns></returns>
        [XmlIgnore]
        public string NodeColorHex => !String.IsNullOrEmpty(options?.NodeColor) ? options.NodeColor : "c1c1c1";
        [XmlIgnore]
        public float NodeWidth => options?.NodeWidth ?? 200;
        [XmlIgnore]
        public float NodeHeight => options?.NodeHeight ?? 150;

        [XmlIgnore]
        private NodeOptionsAttribute _options;
        [XmlIgnore]
        private NodeOptionsAttribute options
        {
            get
            {
                if (_options == null)
                {
                    NodeOptionsAttribute attr = (NodeOptionsAttribute)Attribute.GetCustomAttribute(this.GetType(), typeof(NodeOptionsAttribute));
                    _options = attr;
                }

                return _options;
            }
        }
        [XmlIgnore]
        public List<Language> Languages;
}

[XmlRoot(ElementName = "Connection")]
    public class Output
    {
        [XmlAttribute]
        public Guid ConnectsTo;
        [XmlAttribute]
        public string PortName;
        [XmlAttribute]
        public Direction PortDirection;
        [XmlAttribute]
        public Port.Capacity Capacity;
    }

 public class Dialogue
    {
        /// <summary>
        /// The list of Conversations
        /// </summary>
        [XmlArrayItem(ElementName = "Conversation")]
        public List<Conversation> Conversations;
        /// <summary>
        /// The list of Languages
        /// </summary>
        public List<Language> Languages;

        [XmlIgnore]
        private List<Type> nodeTypes;
        [XmlIgnore]
        public List<Type> NodeTypes
        {
            get
            {
                if (nodeTypes == null)
                {
                    nodeTypes = AppDomain.CurrentDomain.GetAssemblies()
                        .SelectMany(assembly =>
                            assembly.GetTypes())
                            .Where(type =>
                                type.IsSubclassOf(typeof(BaseConversationNode))
                                //&& type.CustomAttributes.Any(x => x.AttributeType != typeof(AutoGeneratedNodeAttribute))
                                && !type.Equals(typeof(StartNode))
                            )
                            .ToList();
                }

                return nodeTypes;
            }
        }
}      

public class Language
    {
        [XmlAttribute]
        public Guid Id;
        public string Name;
        public string Code;
    }  

public class Conversation
    {
        [XmlAttribute]
        public Guid Id;
        [XmlAttribute]
        public string Name;
        [XmlElement(typeof(StartNode), ElementName = "StartNode")]
        [XmlElement(typeof(TextNode), ElementName = "TextNode")]
        public List<BaseConversationNode> Nodes;
}

我觉得这很奇怪,因为我使用的 XML 正是 XML 序列化程序首先返回的内容。你会认为它能够正确反序列化它自己的序列化 XML ......

我在这里想念什么?

亲切的问候,

-弗迪

编辑:忘记添加基类。编辑2:我是一个笨蛋,忘记在第一次编辑时添加其他相关类。

标签: c#xmlxmlserializer

解决方案


我注意到了我的错误。在下面的:

[XmlElement(typeof(StartNode), ElementName = "StartNode")]
[XmlElement(typeof(TextNode), ElementName = "TextNode")]
public List<BaseConversationNode> Nodes;

我应该XmlElement向 Nodes 变量添加另一个属性:

[XmlElement(typeof(StartNode), ElementName = "StartNode")]
[XmlElement(typeof(TextNode), ElementName = "TextNode")]
[XmlElement(typeof(ChoiceNode), ElementName = "ChoiceNode")]
public List<BaseConversationNode> Nodes;

这确实正确地反序列化 XML。


推荐阅读