我有一个与XML序列化兼容的基类和一个实现IXmlSerializable的派生类。
在此示例中,基类确实实现了IXmlSerializable:
using System.Diagnostics;
using System.Text;
using System.Xml;
using System.Xml.Schema;
using System.Xml.Serialization;
namespace XmlSerializationDerived
{
public class Foo
{
public int fooProp;
public XmlSchema GetSchema()
{
return null;
}
public void ReadXml(XmlReader reader)
{
fooProp = int.Parse (reader.ReadElementString ("fooProp"));
}
public void WriteXml(XmlWriter writer)
{
writer.WriteElementString ("fooProp", fooProp.ToString ());
}
}
public class Bar : Foo, IXmlSerializable
{
public new void ReadXml(XmlReader reader)
{
base.ReadXml (reader);
}
public new void WriteXml(XmlWriter writer)
{
base.WriteXml (writer);
}
static void Main(string[] args)
{
StringBuilder sb = new StringBuilder ();
XmlWriter writer = XmlWriter.Create (sb);
Bar bar = new Bar ();
bar.fooProp = 42;
XmlSerializer serializer = new XmlSerializer (typeof (Bar));
serializer.Serialize (writer, bar);
Debug.WriteLine (sb.ToString ());
}
}
}
这会产生此输出:
<?xml version="1.0" encoding="utf-16"?><Bar><fooProp>42</fooProp></Bar>
但是,我想使用不实现IXmlSerializable的基类。这可以防止使用base.Read/WriteXml
。结果将是:
<?xml version="1.0" encoding="utf-16"?><Bar />
有没有办法让你得到理想的结果呢?
答案 0 :(得分:4)
改善mtlung的答案,为什么不使用XmlSerializer?您可以使用属性调整您的类,以便可以按照您希望的方式对其进行序列化,而且这很简单。
using System.Xml.Serialization;
...
[XmlRoot("someclass")]
public class SomeClass
{
[XmlAttribute("p01")]
public int MyProperty01
{
get { ... }
}
[XmlArray("sometypes")]
public SomeType[] MyProperty02
{
get { ... }
}
[XmlText]
public int MyProperty03
{
get { ... }
}
public SomeClass()
{
}
}
然后,序列化和反序列化将非常简单:
void Save(SomeClass obj)
{
XmlSerializer xs = new XmlSerializer(typeof(SomeClass));
using (FileStream fs = new FileStream("c:\\test.xml", ...))
{
xs.Serialize(fs, obj);
}
}
void Load(out SomeClass obj)
{
XmlSerializer xs = new XmlSerializer(typeof(SomeClass));
using (FileStream fs = new FileStream("c:\\test.xml", ...))
{
obj = xs.Deserialize(fs);
}
}
结果XML将是这样的:
<someclass p01="...">
<sometype>
<!-- SomeType serialized objects as child elements -->
</sometype>
# value of "MyProperty03" as text #
</someclass>
这种方法适用于“POCO”类,并且简单而干净。您甚至不必使用这些属性,它们可以帮助您自定义序列化。
答案 1 :(得分:2)
“这可以防止使用base.Read/WriteXml。”
通常,如果基类实现了IXmlSerializable
,您可以使其成为virtual
方法,以便使用具体版本。通常,您还使用显式实现(而不是公共属性) - 可能使用一些protected virtual
方法来实现详细信息(尽管跟踪读者/作者在不同类中的位置将是一场噩梦)。 / p>
AFAIK,在添加派生的位时,无法重新使用XmlSerializer
来编写 base 位。 IXmlSerializable
全有或全无。
答案 2 :(得分:1)
为什么不在读/写函数中简单地使用XmlSerializer?
XmlSerializer s = new XmlSerializer(typeof(Foo));
s.Serialize(writer, base);