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

本文关键字:类型 -TypeName 属性 定义 获胜 派生 序列化 抽象 基类 | 更新日期: 2023-09-27 18:20:28

我的场景:

我定义了一个对象,该对象具有用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>

知道我在这里做错了什么吗?

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

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

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

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

这里有一个很好的教程:如何正确实现IXmlSerializable

此外,这里还有一些很好的信息:实现IXmlSerializable的正确方法?

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

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());
        }
    }