Десериализация зависит от значения поля - PullRequest
1 голос
/ 14 октября 2019

Мне нужно десериализовать XML, который использует поле «тип», чтобы указать, какой контент ожидать. Тип 0 говорит, что я могу ожидать простой текст, в то время как тип 1 указывает, что содержимое имеет более сложную структуру.

Я знаю, что мог бы написать какой-то собственный механизм десериализации, но хотел бы знать, существует ли какой-либо встроенный способчтобы решить это.

Так как XMLSerializer ожидает строку, он просто выбрасывает содержимое в случае, если это XML. Это мешает мне запустить десериализацию контента как второй шаг.

<Msg>
    <MsgType>0</MsgType>
    <Data>Some text</Data>
</Msg>

<Msg>
    <MsgType>1</MsgType>
    <Data>
        <Document>
            <Type>PDF</Type>
            .....
        </Document>
    </Data>
</Msg>

1 Ответ

0 голосов
/ 14 октября 2019

Это не поддерживается из коробки;тем не менее, вы можете использовать:

public XmlNode Data {get;set;}

и выполнить команду «что делать с Data?»в качестве второго шага, как только вы можете посмотреть на MsgType.

Полный пример:

using System;
using System.Collections.Generic;
using System.IO;
using System.Xml;
using System.Xml.Serialization;

static class P
{
    static void Main()
    {
        const string xml = @"<Foo>
<Msg>
    <MsgType>0</MsgType>
    <Data>Some text</Data>
</Msg>

<Msg>
    <MsgType>1</MsgType>
    <Data>
        <Document>
            <Type>PDF</Type>
            .....
        </Document>
    </Data>
</Msg>
</Foo>";
        var fooSerializer = new XmlSerializer(typeof(Foo));
        var docSerializer = new XmlSerializer(typeof(Document));
        var obj = (Foo)fooSerializer.Deserialize(new StringReader(xml));

        foreach (var msg in obj.Messages)
        {
            switch (msg.MessageType)
            {
                case 0:
                    var text = msg.Data.InnerText;
                    Console.WriteLine($"text: {text}");
                    break;
                case 1:
                    var doc = (Document)docSerializer.Deserialize(new XmlNodeReader(msg.Data));
                    Console.WriteLine($"document of type: {doc.Type}");
                    break;
            }
            Console.WriteLine();
        }
    }
}
public class Foo
{
    [XmlElement("Msg")]
    public List<Message> Messages { get; } = new List<Message>();
}
public class Message
{
    [XmlElement("MsgType")]
    public int MessageType { get; set; }

    public XmlNode Data { get; set; }
}

public class Document
{
    public string Type { get; set; }
}
...