Страницы

Поиск по вопросам

среда, 11 декабря 2019 г.

Не работает сериализация объекта из xml в string C#

#c_sharp #алгоритм #xml #serialize


Рутовый класс:

[Serializable]
[XmlRoot("Main")]
public class MainClass
{
    public MainClass()
    {
        Parents = new List();
    }

    [XmlElement("Parent")]
    public List Parents { get; set; }
}


Есть родительский класс:

[Serializable]
[XmlRoot("Parent")]
public class MyParent
{
    public enum myEnum : int
    {
        One,
        Two,
        Three
    };

    [XmlAttribute("Id")]
    public string Id { get; set; }

    [XmlAttribute("Name")]
    public string Name { get; set; }
}   


Есть класс, расширяющий его:

[Serializable]
[XmlRoot("Parent")]
public class MyChild : MyParent
{
    public MyChild()
    {
        Child = new List();
    }

    [XmlElement("Child")]
    public List Child { get; set; }
}


Этот класс раскрывает, что внутри тега Child:

[Serializable]
[XmlRoot("Child")]
public class InnerParameter
{
    public InnerParameter()
    {

    }

    [XmlText]
    public string Value { get; set; }
}


Затем, пытаюсь сериализовать:

MainClass newMainXml = new MainClass();
newMainXml.Parents = new List();
MyChild ch = new MyChild ();

ch.Id = "123";
ch.Name = "Stefani";

InnerParameter parameter = new InnerParameter();
parameter.Value = "MyText";
ch.Child.Add(parameter);

newMainXml.Parents.Add(ch);

XmlSerialization.TrySerializeObjectToXmlString(newMainXml, out result);


Хочу на выходе такую XML:

MyText
Получаю ошибку сериализации: There was an error generating the XML document. The type MyChild was not expected. Use the XmlInclude or SoapInclude attribute to specify types that are not known statically. Подскажите пожалуйста, что я делаю не так в формировании xml? Почему сериализация не работает? (Есть большое подозрение, что дело тут в наследовании и зависимости классов между собой. Наверно, надо сказать, что MyChild не единственный класс, который расширяет MyParent...) P.S.: похоже, что тут ситуация как у меня почти: XML-сериализация объекта с полем типа Object C#


Ответы

Ответ 1



Судя по всему TrySerializeObjectToXmlString у вас реализован примерно так: private static void TrySerializeObjectToXmlString(MainClass ch, out string result) { StringBuilder sb = new StringBuilder(); using (var writer = new StringWriter(sb)) { XmlSerializer s = new XmlSerializer(typeof(MainClass)); s.Serialize(writer, ch); } result = sb.ToString(); } С такой реализацией он падает именно с ошибкой из вопроса. В таком случае должно хватить добавления XmlInclude на тип MyParent: [Serializable] [XmlRoot("Command")] [XmlInclude(typeof(MyChild))] public class MyParent { public enum myEnum : int { One, Two, Three }; [XmlAttribute("Id")] public string Id { get; set; } [XmlAttribute("Name")] public string Name { get; set; } }

Ответ 2



Попробуй так :) internal class Program { private static void Main(string[] args) { var ch = new MyChild(); ch.Id = "123"; ch.Name = "Stefani"; var parameter = new InnerParameter(); parameter.Value = "MyText"; ch.Child.Add(parameter); string result = XmlHelper.ObjectToXmlString(ch); } public static class XmlHelper { public static string ObjectToXmlString(object obj) { var xmlSerializer = new XmlSerializer(obj.GetType()); using (var textWriter = new StringWriter()) { xmlSerializer.Serialize(textWriter, obj); return textWriter.ToString(); } } } } Т.к. был отредактирован вопрос - вот новое решение исправления ошибки, которое выдает Ваш код: [Serializable, XmlInclude(typeof(MyChild))] [XmlRoot("Main")] Просто добавьте XmlInclude(typeof(MyChild)) для класса MainClass, т.к. он ничего не знает о MyChild это позволит ему распознать MyChild в процессе сериализации.

Ответ 3



Проблема решается действительно добавлением [XmlInclude(typeof(MyChild))] таким образом: [Serializable] [XmlRoot("Parent")] [XmlInclude(typeof(MyChild))] public class MyParent { public enum myEnum : int { One, Two, Three }; [XmlAttribute("Id")] public string Id { get; set; } [XmlAttribute("Name")] public string Name { get; set; } } Моя ошибка была в том, что (для сравнения) у меня было написано так: [Serializable] [XmlRoot("Parent")] [XmlInclude(typeof(MyChild)), XmlInclude(typeof(HisChild)), XmlInclude(typeof(HerChild))] public class MyParent { public enum myEnum : int { One, Two, Three }; [XmlAttribute("Id")] public string Id { get; set; } [XmlAttribute("Name")] public string Name { get; set; } } Однако, как я уже говорил, MyChild - не единственный класс, реализующий MyParent, и эти наследники так же необходимо сериализовать. Вот тут хорошая статья: Xml Сериализация и наследование

Комментариев нет:

Отправить комментарий