【问题标题】:How can I determine the class of an XML serialized object in C# before I deserialize it?在反序列化之前,如何在 C# 中确定 XML 序列化对象的类?
【发布时间】:2017-06-04 23:00:22
【问题描述】:

我有一个服务器,它接受作为 XML 序列化对象的请求,这些对象可以是 10 个左右不同的类中的任何一个。当然,为了让服务器处理请求,它必须首先将 XML 字符串反序列化回一个对象。为此,它需要知道对象来自哪个类以选择正确的反序列化器并重新构造对象。因此,最好能够在尝试反序列化之前快速检查 XML 字符串以获取对象类型,然后选择适当的反序列化器。

我一直在使用以下代码,但是,就像歌曲中所说的那样,“我知道必须有更好的方法......”任何建议或见解都将不胜感激。

 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;
    }

【问题讨论】:

    标签: c# xml serialization


    【解决方案1】:

    XML 反序列化器在反序列化之前不需要知道它是什么类型。 MSDN Article about the Deserialize method 有一些关于它的有用信息,当然它有一个代码 sn-p,我把它放在下面。

    我认为您可能对服务器会将其反序列化为对象但不知道如何处理它这一事实感到困惑。您始终可以为ReturnedObject.GetType() 方法的结果执行switch case 并计算出您需要用它做什么。

    你可以像这样将它序列化为一个对象:

     var ReturnedObject = XMLSerializer.Deserialize(reader); 
    

    那你可以继续做

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

    【讨论】:

    • 很好的答案 - 谢谢。我的问题不清楚。我真的只需要知道如何在 switch 语句中处理反序列化的对象,就像你建议的那样。我比我更喜欢你的方法,但是当我尝试用我自己的类似代码复制代码时,我得到如下编译器错误;“错误 1 ​​开关表达式或案例标签必须是布尔、字符、字符串、整数、枚举, 或对应的可为空类型 F:\Documents and Settings\Tom\my documents\visual studio 2010\Projects\Serialization Experiment\Serialization Experiment\Form1.cs 48 21 Serialization Experiment
    • 如果我将 ReturnedObject.GetType() 转换为字符串并打开它,看起来这是一个很好的答案。
    • 虽然“XML Deserializer 在反序列化之前不需要知道它是什么类型”是真的,但看起来您在第一次创建 Deserializer 时确实需要知道对象类型。但我可能会遗漏一些东西。 @Butler1233
    • 我对 XML 序列化程序的记忆不是最好的,但我认为您可以使用对象类型对其进行实例化。这不是最好的方法,但我认为它应该有效。我对序列化为二进制的二进制格式化程序更加熟悉,我发现它更加灵活。而且您不必使用 Binary 构造无参数构造函数。如果您对此感兴趣,我可以为您提供有关如何使用它的详细信息。如果您通过网络发送原始字节流,它可能会更好。
    • 但是,如果您使用的是网络通信,并且两端都是.Net,那么使用WCF会更好,这似乎也是一个巨大的痛苦,让生活变得如此很容易,主要是因为您可以像使用本地代码一样与服务器交互。
    【解决方案2】:

    如果你真的愿意,你可以像这样阅读第三个元素:

    using (XmlReader xr = XmlReader.Create(GenerateStreamFromString(xml.ToString())))
    {
        xr.Read();
        xr.Read();
        xr.Read();
    
        textBox1.Text =  xr.Name;
    }
    

    使用这个辅助函数:

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

    省略所有检查..

    如果您愿意,您可以测试第一个元素是否为 xml 而第二个元素是否为空。 我不确定这是否是个好主意。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-10-11
      • 2020-03-10
      • 1970-01-01
      • 2018-07-17
      • 2023-03-29
      • 1970-01-01
      • 2010-09-18
      • 1970-01-01
      相关资源
      最近更新 更多