【问题标题】:How to deserialize to a dynamic type如何反序列化为动态类型
【发布时间】:2013-10-08 11:06:57
【问题描述】:

我试图反序列化我的 XML 以获得一个动态创建的类型的数组(使用 codedom),然后我使用反射来加载该程序集并加载动态创建的类型。当我尝试反序列化我的 XML(它有一个动态生成类型的对象集合)时,我不确定如何将类型提供给序列化程序。

我的代码示例:

        Assembly assembly = Assembly.LoadFile("myDynamicassembly.dll");
        Type type = assembly.GetType("myDynamicType");

        string xmlstring = myXml.OuterXml.ToString();
        byte[] buffer = ASCIIEncoding.UTF8.GetBytes(xmlstring);
        MemoryStream ms = new MemoryStream(buffer);
        XmlReader reader = new XmlTextReader(ms);

        myDynamicType[] EQs;
        XmlSerializer serializer = new XmlSerializer(typeof(myDynamicType[]));
        EQs = (myDynamicType[])(serializer.Deserialize(reader));

所以,这里的问题是我在编写代码时不知道“myDynamicType”。它将在运行时创建和编译。

请帮忙。

【问题讨论】:

  • 您知道编译时的类型,还是您正在加载完全未知的程序集?你打算如何使用这些对象?
  • 不,我不知道编译时的类型。实际上,它将在运行时生成并编译为程序集。因此,您可以说我的程序集以及我的“myDynamicType”在编译时都是完全未知的。就进一步的使用而言,我将把这个数组传递给我的 Web 服务,该服务将对这个集合执行一些操作。

标签: c# xml serialization


【解决方案1】:

这里的技巧是Type 实例上的Type.MakeArrayType() 方法。无参数版本产生 vector 类型,即typeof(Foo).MakeArrayType() === typeof(Foo[])。多维数组等还有其他重载。

XmlSerializer serializer = new XmlSerializer(type.MakeArrayType());

但是:你将能够在最后施放它;您将需要使用object[] 或类似的(使用引用类型的数组变化):

EQs = (object[])(serializer.Deserialize(reader));

【讨论】:

  • 谢谢马克。但是,如果我将其转换为 object[],我将无法将其传递给需要特定类型集合的 Web 服务。
  • @AshishAgrawal 如果类型是动态加载的,那么你已经有问题了。无论您如何键入它,它基本上都是 of 的。如果类型是静态已知的,那么坦率地说,所有这些都是毫无意义的。
  • 类型不是静态定义的。实际上,正如我所说,我正在使用 codedom 来创建“myDynamicType”。所以,这个字符串是可变的,会根据用户的一些输入而改变。例如,如果用户说我想创建一个 Student 类,那么我的代码将更改为: Student[] EQs; XmlSerializer 序列化器 = 新 XmlSerializer(typeof(Student[])); EQs = (Student[])(serializer.Deserialize(reader));如果我在这里造成任何混乱,请告诉我。
  • @AshishAgrawal 问题是最后一点 - EQ。对于不是(也不能是)静态类型的变量,很难做任何有用的事情。您需要使用反射或dynamic
  • 让我在这里尝试解释我的确切要求。我有一个 Web 服务,它根据客户端提供的信息(通过 url)动态生成 wsdl。例如,如果用户尝试访问“myServiceHost/myWebService/A.asmx?wsdl”;然后 wsdl 显示一些方法,如 GetA(A[] records)、CreateA(A[] records)、DeleteA(A[] records) 等。其中 A 将是可序列化的类型。假设如果用户尝试访问 url myServiceHost/myWebService/B.asmx?wsdl,那么它将显示一些方法,如 GetB(B[] records)、CreateB(B[] records)、DeleteB(B[] records) contd
【解决方案2】:

我不知道我要说的是不是你想要的,但是:

你不能将它反序列化为对象类型

object[] EQs;
XmlSerializer serializer = new XmlSerializer(typeof(object[]));
EQs = (object[])(serializer.Deserialize(reader));

如果对象类型是在编译时定义的(如您所说),不应该有一些代码来定义它吗?在那段代码中,您只需将对象转换为您想要的类型?

拥有object[] EQs 后的另一种转换方式如下:

     if(EQs.Lenght > 0)
     {
        Type t = EQs[0].GetType();
     }

现在使用获得的Type 将您的object[] EQs 转换为右侧Type

【讨论】:

  • “你不能将它反序列化为对象类型吗” - 不,基本上; XmlSerializer 需要知道它应该期待什么
  • @Vincent,实际上我正在使用 codedom 动态(在运行时)创建该类型。这是我在运行时获取类型的代码(基于用户的输入)。类型 type = assembly.GetType("myDynamicType");所以,myDynamicType 不是静态定义的类型。
  • 那么它可以是什么类型?我们谈论的可能是字符串,也可能是数字。或者它可能是自定义类。更重要的是,你需要用它来计算/做东西吗?如果它只是为了从 xml 加载以在屏幕上显示某个字符串就足够了。
  • @VincentAdvocaat 它可以是任何自定义类型,并将包含多种方法(请参阅我对 Marc 上述回答的评论)。我将把这个集合传递给我的网络服务(对那个集合做一些操作)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-10-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多