如何在事先不知道类型的情况下使用 XmlSerializer 反序列化可能属于基类或派生类的对象?
在 C# 中,如何在事先不知道类型的情况下使用 XmlSerializer 反序列化可能属于基类或任何多个派生类的对象?
我的所有派生类都添加了额外的数据成员。我制作了一个简单的 GUI,可以序列化和反序列化类对象。它将根据用户选择填充的字段将对象序列化为适当的继承类(甚至只是基类)。
我对序列化没有任何问题;问题是反序列化。在事先不知道类的情况下,如何让 XmlSerializer 将数据反序列化到正确的派生类?我目前创建了一个 XmlReader 来读取 XML 文件的第一个节点并从中确定类,它似乎可以满足我的目的,但它似乎是一个极其不优雅的解决方案。
我在下面发布了一些示例代码。有什么建议吗?
BaseType objectOfConcern = new BaseType();
XmlSerializer xserializer;
XmlTextReader xtextreader = new XmlTextReader(DEFAULT_FILENAME);
do { xtextreader.Read(); } while (xtextreader.NodeType != XmlNodeType.Element);
string objectType = xtextreader.Name;
xtextreader.Close();
FileStream fstream = new FileStream(DEFAULT_FILENAME, FileMode.Open);
switch (objectType)
{
case "type1":
xserializer = new XmlSerializer(typeof(DerivedType));
objectOfConcern = (DerivedType)xserializer.Deserialize(fstream);
//Load fields specific to that derived type here
whatever = (objectOfConcern as DerivedType).NoOfstreamubordinates.ToString();
case "xxx_1":
//code here
case "xxx_2":
//code here
case "xxx_n":
//code here
//and so forth
case "BaseType":
xserializer = new XmlSerializer(typeof(BaseType));
AssignEventHandler(xserializer);
objectOfConcern = (BaseType)xserializer.Deserialize(fstream);
}
//Assign all deserialized values from base class common to all derived classes here
//Close the FileStream
fstream.Close();
In C#, how do I use an XmlSerializer
to deserialize an object that might be of a base class, or of any of several derived classes without knowing the type beforehand?
All of my derived classes add additional data members. I've made a simple GUI that can serialize and deserialize class objects. It will serialize objects as whatever inherited class (or even just the base class) is appropriate based on which fields the user chooses to populate.
I have no issues with the serialization; the problem is the deserialization. How can I possibly have the XmlSerializer
deserialize data to the correct derived class without knowing the class beforehand? I currently create an XmlReader
to read the first node of the XML file and determine the class from it, and it seems to work for my purposes, but it seems like an extremely inelegant solution.
I've posted some sample code below. Any suggestions?
BaseType objectOfConcern = new BaseType();
XmlSerializer xserializer;
XmlTextReader xtextreader = new XmlTextReader(DEFAULT_FILENAME);
do { xtextreader.Read(); } while (xtextreader.NodeType != XmlNodeType.Element);
string objectType = xtextreader.Name;
xtextreader.Close();
FileStream fstream = new FileStream(DEFAULT_FILENAME, FileMode.Open);
switch (objectType)
{
case "type1":
xserializer = new XmlSerializer(typeof(DerivedType));
objectOfConcern = (DerivedType)xserializer.Deserialize(fstream);
//Load fields specific to that derived type here
whatever = (objectOfConcern as DerivedType).NoOfstreamubordinates.ToString();
case "xxx_1":
//code here
case "xxx_2":
//code here
case "xxx_n":
//code here
//and so forth
case "BaseType":
xserializer = new XmlSerializer(typeof(BaseType));
AssignEventHandler(xserializer);
objectOfConcern = (BaseType)xserializer.Deserialize(fstream);
}
//Assign all deserialized values from base class common to all derived classes here
//Close the FileStream
fstream.Close();
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
您有一些包含派生类型的根类/标签吗?如果是,您可以使用 XmlElementAttribute 将标记名称映射到类型:
Have you some root class/tag which contains that derived types? If yes, you can use XmlElementAttribute to map tag name to type:
我最近为基类 T 和 T 的任何派生类编写了这个通用序列化器\反序列化器。
到目前为止似乎有效。
Type[] 数组存储 T 和 T 本身的所有派生类型。
解串器会尝试其中的每一个,并在找到正确的时返回。
I recently wrote this generic serializer\deserializer for base class T and any derived classes of T.
Seems to work so far.
The Type[] array stores all the derived types of T and T itself.
The deserializer tries each of them, and returns when it found the right one.
如果您不打算使用
XmlSerializer
,您可以使用DataContractSerializer
与KnownType
属性代替。您需要做的就是为每个子类向父类添加一个
KnownType
属性,然后DataContractSerializer
将完成剩下的工作。DataContractSerializer
将在序列化为 xml 时添加类型信息,并在反序列化时使用该类型信息来创建正确的类型。例如,以下代码:
将输出:
在输出中,您会注意到 c2 和 c3 的 xml 包含额外的类型信息,这些信息允许
DataContractSerializer.ReadObject
创建正确的类型。If you're not set upon using the
XmlSerializer
you can use theDataContractSerializer
with theKnownType
attribute instead.All you need to do is add a
KnownType
attribute to the parent class for each sub class and theDataContractSerializer
will do the rest.The
DataContractSerializer
will add type information when serializing to xml and use that type information when deserializing to create the correct type.For example the following code:
Will output :
In the output you'll notice the xml for c2 and c3 contained extra type information which allowed the
DataContractSerializer.ReadObject
to create the correct type.您可以尝试使用构造函数 XmlSerializer(Type type, Type[] extraTypes) 创建一个适用于所有涉及的类型的序列化器。
You could try to use the constructor XmlSerializer(Type type, Type[] extraTypes) to create a serializer that works with all involved types.
则可以使用 XmlInclude否则:
如果您想在序列化时添加类型,
you can use XmlInclude
otherwise if you want to add the types when serializing: