简体   繁体   中英

How can I determine the class of an XML serialized object in C# before I deserialize it?

I have a server that accepts requests as XML serialized objects which could be any of 10 or so different Classes. Of course in order for the server to process the request, it must first de-serialize the XML string back into an object. To do that, it needs to know what class the object came from to choose the correct de-serializer and re-construct the object. So it would be good to be able to just quickly inspect the XML string before attempting to de-serialize it to get the object type and then select the appropriate de-serializer.

I have been using the following code, but, like the song goes, "I know there's got to be a better way..." Any suggestions or insight would be appreciated.

 private void button1_Click(object sender, EventArgs e)
    {
        //any class - does not matter - create an object
        SomeClass tc = new SomeClass();
        //populate it
        tc.i = 5;
        tc.s = "Hello World";
        tc.d = 123.456;

        //Serialize it to XML
        StringWriter xml = new StringWriter();
        System.Xml.Serialization.XmlSerializer x = new System.Xml.Serialization.XmlSerializer(typeof(SomeClass));
        x.Serialize(xml, tc);

        //Extract the Class name and show the XML to the user without de-serializing it
        textBox1.Text = GetClassNameFromXMLSerializedString(xml.ToString());
    }

    private string GetClassNameFromXMLSerializedString(string xml)
    {
        //The class name is somewhere in the xml
        string classname = xml;
        //get the start of class name
        classname = xml.Substring(classname.IndexOf('>') + 4);
        //get the class name which is terminated by a space
        classname = classname.Substring(0, classname.IndexOf(' '));
        //return it
        return classname;
    }

The XML Deserializer does not need to know what type it is before deserializing. The MSDN Article about the Deserialize method has some useful information about it and of course it has a code snippet, which I've put below.

I think you might have confused yourself with the fact that the server will deserialize it to an object, but then won't know what to do with it. You can always do a switch case for the result of the ReturnedObject.GetType() method and work out what you need to do with it.

You can just serialize it to an object like this:

 var ReturnedObject = XMLSerializer.Deserialize(reader); 

Then you can go ahead and do

 switch (ReturnedObject.getType())
 {
     case MyClass:
         // Insert code here 
     case AnotehrClass:
         //Do something else here for another class
 }

If you really want to you can read the 3rd element like this:

using (XmlReader xr = XmlReader.Create(GenerateStreamFromString(xml.ToString())))
{
    xr.Read();
    xr.Read();
    xr.Read();

    textBox1.Text =  xr.Name;
}

Using this helper function:

public static MemoryStream GenerateStreamFromString(string value)
{
    return new MemoryStream(Encoding.Unicode.GetBytes(value ?? ""));
}

All checks omitted..

If you want to you can test if the 1st element is xml and the 2nd one is empty. I'm not really sure if this is a good idea.

XDocument xd = XDocument.Parse(xml.ToString()); switch (xd.Root.Name.ToString()) { case "Class1": //do something break; case "Class2": //do something break; }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM