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>
知道我在这里做错了什么吗?
将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());
}
}