8bitcartridge 8bitcartridge - 1 year ago 44
C# Question

How do I use an XmlSerializer to deserialize an object that might be of a base or derived class without knowing the type beforehand?

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

Answer Source

Have you some root class/tag which contains that derived types? If yes, you can use XmlElementAttribute to map tag name to type:

public class RootElementClass
{
    [XmlElement(ElementName = "Derived1", Type = typeof(Derived1BaseType))]
    [XmlElement(ElementName = "Derived2", Type = typeof(Derived2BaseType))]
    [XmlElement(ElementName = "Derived3", Type = typeof(Derived3BaseType))]
    public BaseType MyProperty { get; set; }
}

public class BaseType { }
public class Derived1BaseType : BaseType { }
public class Derived2BaseType : BaseType { }
public class Derived3BaseType : BaseType { }
Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download