Десериализация объекта с игнорированием определенных узлов - PullRequest
0 голосов
/ 28 мая 2020

У меня есть объект, который я сериализовал с помощью 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>

Все текстовые узлы десериализуются правильно, но 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: Я дурак и забыл добавить другие соответствующие классы при первом редактировании.

1 Ответ

1 голос
/ 28 мая 2020

Я заметил свою ошибку. В следующем примере:

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

Я должен был добавить еще один атрибут XmlElement в переменную узлов:

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

Это десериализует XML правильно.

...