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

C# 抽象基类型到派生类型的C Xml序列化-哪个TypeName属性定义获胜?,c#,xml-serialization,derived-class,abstract-base-class,C#,Xml Serialization,Derived Class,Abstract Base Class,我的设想: 我有一个我用属性定义的对象,这些属性用XmlElement标记修饰,并且有我定义的类型,其中一些类型是抽象类型,设置为各自的派生类型。我想使用XmlSerializer将整个对象序列化为XML,所有抽象属性都应该序列化为元素,并将TypeName设置为派生类型的TypeName 以下是对象的结构示例: [XmlType(TypeName = "MAINOBJECT")] public class MainObject { [XmlElement(Type = typeof(D

我的设想:

我有一个我用属性定义的对象,这些属性用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>

知道我做错了什么吗

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

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

将XmlElement名称添加到Main对象中的Base中,如下所示:

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

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

这里有一个很好的教程:


另外,这里还有一些很好的信息:

请理解,我不想硬编码元素的名称,我希望它动态选择从基类派生的任何类作为其类型名,我分配给基类。序列化不是这样工作的,因为如果有多个相同类型的属性,就无法区分它们。例如,public BaseClass TheBase和public BaseClass TheBase2。在这种情况下,第一个默认为base,第二个默认为base2,除非您指定了类型名。但是,我为要分配给基的派生类型指定了一个类型名。我希望它在序列化时使用派生类型的TypeName。我想的不对吗?是的,它类似于一个字符串属性,命名为string。例如,如果你有一个公共字符串TheBase,你希望序列化的名称是或吗?好吧,这很管用lol。我应该在一开始放弃它之前至少尝试一下,非常感谢:我的意思是[XmlElementDERIVEDCLASS,Type=typeofDerivedClass]公共基类TheBase{get;set;}我现在将研究使用IXmlSerializable,如果我能让我的实现正常工作,我将把它标记为正确答案。谢谢