XML сериализация подкласса - PullRequest
0 голосов
/ 14 июля 2011

У меня есть класс:

public abstract class BaseClass
{

}

public class FirstChild:BaseClass
{

}

public class SecondChild:BaseClass
{

}

public class Request
{
public BaseClass Child {get;set;}

}

Я добавил атрибут сериализации для всех классов и включил XmlInclude для классов Baseclass, firstchild и secondchild.

I want to achieve this:
<Request>
   <FirstChild/>
</Request>

или

<Request>
   <SecondChild/>
</Request>

Я создаю запрос, используя:

Request request = new Request();
request.Child = new FirstChild();

И затем сериализую его.

но я продолжаю получать это:

<Request  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">

<Type  xsi:type="FirstChild">
</Type>

</Request>

Можете ли выпожалуйста, укажите, что я делаю не так?

Ответы [ 3 ]

5 голосов
/ 22 мая 2012

Для этого вам нужно использовать атрибуты XmlArrayItem или XmlElement.Кроме того, если вы хотите, чтобы подклассифицированный экземпляр был подэлементом вашего элемента Child, проще, если вы обрабатываете свойство Child как BaseClass [] длины 1.

Таким образом, ваш класс будет выглядеть следующим образомэто:

public abstract class BaseClass
{

}

public class FirstChild:BaseClass
{

}

public class SecondChild:BaseClass
{

}

public class Request
{
        [XmlArrayItem(Type = typeof(FirstChild), ElementName = "FirstChild")]
        [XmlArrayItem(Type = typeof(SecondChild), ElementName = "SecondChild")] 
        public BaseClass[] Child {get;set;}

}

Это приведет к XML, который вы ищете.

0 голосов
/ 14 июля 2011

Я не вижу простого способа сделать это.Для этого я бы создал вспомогательный класс RequestMemento:

using System;
using System.IO;
using System.Xml.Serialization;
using System.ComponentModel;

public abstract class BaseClass
{}

public class FirstChild:BaseClass
{}

public class SecondChild:BaseClass
{}

[XmlRoot("Request")]
[XmlType("Request")]
public class RequestMemento
{
    [DefaultValue(null)]
    public FirstChild First { get; set; }

    [DefaultValue(null)]
    public SecondChild Second { get; set; }

    [XmlIgnore]
    public BaseClass Child
    {
        get
        {
            return (BaseClass)First ?? (BaseClass)Second;
        }
        set
        {
            First = value as FirstChild;
            Second = value as SecondChild;
        }
    }
}

class App
{
    static void Main()
    {
        var memento = new RequestMemento();
        memento.Child = new FirstChild();

        XmlSerializer serializer = new XmlSerializer(typeof(RequestMemento));
        using (var writer = new StreamWriter("1.xml"))
        {
            serializer.Serialize(writer, memento);
        }
    }
}
0 голосов
/ 14 июля 2011

Можете ли вы попробовать этот код ... также я предполагаю, что ваш реальный класс имеет свойства в них.

using (MemoryStream ms = new MemoryStream())
{
    XmlWriterSettings xrs = new XmlWriterSettings();
    xrs.Encoding = Encoding.UTF8;
    using (XmlWriter writer = XmlWriter.Create(ms, xrs))
    {
        XmlSerializer serializer = new XmlSerializer(obj.GetType());
        serializer.Serialize(writer, obj);

        writer.Flush();
    }

    using (StreamReader sr = new StreamReader(ms))
    {
        ms.Position = 0;
        xml = sr.ReadToEnd();
    }
}
...