Десериализация XML в соответствующий тип на основе атрибутов, присутствующих в XML C # - PullRequest
0 голосов
/ 03 октября 2019

Я столкнулся с проблемой десериализации XML для соответствующего типа. Запрос вашей помощи.

У меня есть два XML-файла. oldXML.xml и newXML.xml ниже соответственно

  <?xml version="1.0"?>
  <root>
    <elementOne>101</elementOne>
    <elementTwo>10</elementTwo>
  </root>

И

<?xml version="1.0"?>
  <root>
    <elementOne>101</elementOne>
    <elementTwo>10</elementTwo>
    <elementThree>10</elementThree>
  </root>

newXML.xml имеет дополнительный атрибут "elementThree"

Я написал 3 класса длядесериализовать XML-файлы в

    public abstract class ResponseBase
    {
        public abstract void PrintResult();

    }
    public class OldXML : ResponseBase
    {
        [XmlElement("elementOne")]
        public string ElementOne { get; set; }
        [XmlElement("elementTwo")]
        public string ElementTwo { get; set; }

        public override void PrintResult()
        {
            Console.WriteLine("Result is of type 'OldXML': {0}, {1}", ElementOne, ElementTwo);
        }
    }

    public class NewXML : ResponseBase
    {
        [XmlElement("elementOne")]
        public string ElementOne { get; set; }
        [XmlElement("elementTwo")]
        public string ElementTwo { get; set; }
        [XmlElement("elementThree")]
        public string ElementThree { get; set; }

        public override void PrintResult()
        {
            Console.WriteLine("Result is of type 'NewXML': {0}, {1}, {2}", ElementOne, ElementTwo, ElementThree);
        }
    }

И я хочу десериализовать их, как показано ниже

    ResponseBase result1= MethodToDeserializeToBeWritten(File.ReadAllText("oldXML.json"))
    ResponseBase result2= MethodToDeserializeToBeWritten(File.ReadAllText("newXML.json"))
    result1.PrintResult()
    result2.PrintResult()

Когда я вызываю метод PrintResult, во власти полиморфизма в OOPS должна быть вызвана реализация дочернего класса( Не работает , выдает ошибку, что не может быть создан экземпляр абстрактного класса). Обратите внимание, что эти XML являются лишь примерами, и код должен работать для любых таких XML.

Кроме того, XML получен от клиента, и поэтому мы не можем изменить XML.

Причинав будущем мы можем получить новый XML с новым атрибутом, скажем, «elementFour». Для этого мы будем добавлять новый класс и не трогать существующую реализацию.

Заранее спасибо.

1 Ответ

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

Вам необходимо создать общий метод MethodToDeserializeToBeWritten.

public class XML
{
    public static T Deserialize<T>(string input)
    {
        var serializer = new XmlSerializer(typeof(T));
        using (TextReader textReader = new StringReader(input))
        {
            return (T)serializer.Deserialize(textReader);
        }
    }
}


public abstract class ResponseBase
{
    public abstract void PrintResult();

}

[XmlRoot("root")]
public class OldXML : ResponseBase
{
    [XmlElement("elementOne")]
    public string ElementOne { get; set; }
    [XmlElement("elementTwo")]
    public string ElementTwo { get; set; }

    public override void PrintResult()
    {
        Console.WriteLine("Result is of type 'OldXML': {0}, {1}", ElementOne, ElementTwo);
    }
}

[XmlRoot("root")]
public class NewXML : ResponseBase
{
    [XmlElement("elementOne")]
    public string ElementOne { get; set; }
    [XmlElement("elementTwo")]
    public string ElementTwo { get; set; }
    [XmlElement("elementThree")]
    public string ElementThree { get; set; }

    public override void PrintResult()
    {
        Console.WriteLine("Result is of type 'NewXML': {0}, {1}, {2}", ElementOne, ElementTwo, ElementThree);
    }
}


class Program
{
    static void Main(string[] args)
    {
        string rootFilePath = @"C:\test\";
        ResponseBase result1 = MethodToDeserializeToBeWritten<OldXML>(File.ReadAllText($"{rootFilePath}oldXML.xml"));
        ResponseBase result2 = MethodToDeserializeToBeWritten<NewXML>(File.ReadAllText($"{rootFilePath}newXML.xml"));
        result1.PrintResult();
        result2.PrintResult();
    }

    static ResponseBase MethodToDeserializeToBeWritten<T>(string fileContent) where T : ResponseBase
    {
        return XML.Deserialize<T>(fileContent);
    }
}

ВЫХОД:

Результат имеет тип 'OldXML': 101,10

Результат имеет тип 'NewXML': 101, 10, 10

Или вы можете избавиться от метода MethodToDeserializeToBeWritten и упростить ваш код следующим образом:

ResponseBase result1 = XML.Deserialize<OldXML>(File.ReadAllText($"{rootFilePath}oldXML.xml"));
ResponseBase result2 = XML.Deserialize<NewXML>(File.ReadAllText($"{rootFilePath}newXML.xml"));

Также обратите внимание, что вам нужно пометить OldXML и NewXML атрибутом XmlRoot. В противном случае вы получите исключение.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...