简体   繁体   English

在反序列化之前,如何在 C# 中确定 XML 序列化对象的类?

[英]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.我有一个服务器接受作为 XML 序列化对象的请求,这些对象可以是 10 个左右不同的类中的任何一个。 Of course in order for the server to process the request, it must first de-serialize the XML string back into an object.当然,为了让服务器处理请求,它必须首先将 XML 字符串反序列化为一个对象。 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.因此,最好能够在尝试反序列化 XML 字符串之前快速检查它以获取对象类型,然后选择适当的反序列化器。

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. 反序列化之前,XML Deserializer不需要知道它是什么类型。 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. 有关反序列化方法MSDN文章提供了一些有用的信息,当然还有一个代码段,我将其放在下面。

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. 您始终可以对ReturnedObject.GetType()方法的结果进行switch case ,并计算出需要使用的方法。

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. 如果愿意,可以测试第一个元素是否为xml ,第二个元素是否为空。 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; }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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