我的情景:
我有一个使用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>
任何线索我在这里做错了什么?
答案 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());
}
}