C#Xml-将抽象基类型序列化为派生类型 - 哪个TypeName属性定义获胜?

时间:2014-09-03 17:31:42

标签: c# xml-serialization derived-class abstract-base-class

我的情景:

我有一个使用XmlElement标签修饰的属性定义的对象,这些属性具有我定义的类型,其中一些类型被设置为抽象,可以设置为各自的派生类型。我想使用XmlSerializer将整个对象序列化为XML,并且所有抽象属性都应该序列化为TypeName设置为派生类型的TypeName的元素。

这是对象结构的一个例子:

[XmlType(TypeName = "MAINOBJECT")]
public class MainObject
{
    [XmlElement(Type = typeof(DerivedClass))]
    public BaseClass TheBase { get; set; }
}

[XmlInclude(typeof(DerivedClass))]
public abstract class BaseClass
{
    [XmlAttribute("AnAttribute")]
    public string AnAttribute { get; set; }

    [XmlElement("ANELEMENT")]
    public string AnElement { get; set; }

}

[XmlType(TypeName = "DERIVEDCLASS")]
public class DerivedClass : BaseClass
{
    [XmlElement("ANOTHERELEMENT")]
    public string AnotherElement { get; set; }

}

但请注意,当我创建一个新的MainObject实例时,填充它的属性并将其序列化,这就是生成的XML的样子:

<MAINOBJECT>
    <BaseClass AnAttribute="">
            <ANELEMENT/>
            <ANOTHERELEMENT/>
    </BaseClass>
</MAINOBJECT>

我想要的是:

<MAINOBJECT>
    <DERIVEDCLASS AnAttribute="">
            <ANELEMENT/>
            <ANOTHERELEMENT/>
    </DERIVEDCLASS>
</MAINOBJECT>

任何线索我在这里做错了什么?

3 个答案:

答案 0 :(得分:1)

将{xmlElement名称添加到TheBase中的MainObject,如下所示:

[XmlType(TypeName = "MAINOBJECT")]
public class MainObject
{
    [XmlElement("DERIVEDCLASS", Type = typeof(DerivedClass))]
    public BaseClass TheBase { get; set; }
}

答案 1 :(得分:1)

在我看来,这里最好的解决方案是实现IXmlSerializable接口,以便您可以完全控制对象的序列化方式。当然,这是更多的工作,但如果你有这样的要求有点不同寻常,那么你可能会遇到更多的怪癖,标准的XmlSerializer将无法在你的路上为你工作。

这里有一个很好的教程:How to Implement IXmlSerializable Correctly

此外,这里有一些很好的信息:Proper way to implement IXmlSerializable?

答案 2 :(得分:0)

也许不是最好的解决方案,但是:

class Program
    {
        static void Main(string[] args)
        {
            XmlAttributes attrs = new XmlAttributes();

            XmlElementAttribute attr = new XmlElementAttribute();
            attr.ElementName = "DerivedClass";
            attr.Type = typeof(DerivedClass);

            attrs.XmlElements.Add(attr);

            XmlAttributeOverrides attrOverrides = new XmlAttributeOverrides();

            attrOverrides.Add(typeof(MainObject), "TheBase", attrs);

            XmlSerializer s = new XmlSerializer(typeof(MainObject), attrOverrides);

            StringWriter writer = new StringWriter();

            MainObject mo = new MainObject { TheBase = new DerivedClass { AnAttribute = "AnAttribute", AnElement = "AnElement", AnotherElement = "AotherElement" } };

            s.Serialize(writer, mo);
            Console.Write(writer.ToString());
        }
    }