使用动态类型/将字符串转换为System.Type来反序列化XML

时间:2021-05-10 17:07:02

Hmmm I'm not sure if i titled this question properly or am asking it properly, but here goes.

嗯,我不确定我是否正确地提出了这个问题,或者我是否正确地提出这个问题。

I've got serialized objects (in XML) stored in a database, along with a string/varchar indicating the type.

我有一个存储在数据库中的序列化对象(XML),以及一个指示类型的字符串/ varchar。

Right now i am doing this: (because i have a finite number of different types)

现在我这样做:(因为我有不同类型的有限数量)

Dim deserializer as XmlSerializer
If datatable("type") = "widget1" then 
     deserializer = new XmlSerializer(GetType(Widget1))
elseif datatable("type") = "widget2" then 
     deserializer = new XmlSerializer(GetType(Widget2))
...

i'd like to do something like

我想做点什么

Dim deserializer as XmlSerializer
deserializer = new XmlSerializer(MagicallyConvertToSystemDotType(datatable("type"))

Am i barking up the wrong tree here?

我在这里吠叫错了树吗?

3 个解决方案

#1


Have you tried using Type.GetType? This takes a string parameter and returns a type for that name. You may have to give it additional information about the simple name "widget" and more along the lines of a full name. But it appears from your sample they should all have the same namespace so that shouldn't be a big hurdle.

你尝试过使用Type.GetType吗?这将获取一个字符串参数并返回该名称的类型。您可能需要提供有关简单名称“小部件”的更多信息以及更多全名的信息。但是从你的示例中看,它们应该都具有相同的命名空间,因此不应该是一个很大的障碍。

#2


The other option if you want an actual keyword Type to work with, and not a variable type is using something like (sorry I'm using C# and am too tired to do the VB conversion):

另一个选项,如果你想要一个实际的关键字Type使用,而不是一个变量类型使用类似的东西(对不起,我正在使用C#,我太累了,无法进行VB转换):

method in XmlSerializer like Deserialize(typestring, object);
method in XmlSerializer like Deserialize<T>(object);


public void Deserialize(string typestring, object obj)
{
  MethodInfo deserialize = typeof(XmlSerializer)
      .GetMethod("Deserialize", BindingFlags.Instance | BindingFlags.Public)
      .MakeGenericMethod(new Type[] { Type.GetType(typestring) });
  deserialize.Invoke(this, new[] { obj });
}

#3


Specifically, I think you're looking for this code here (NOTE: I don't work much in VB.Net, so I hope everything there is syntactically correct):

具体来说,我认为你在这里寻找这个代码(注意:我在VB.Net中工作不多,所以我希望所有语法都正确):

VB.Net:

// Get the type of object being deserialized.
Dim t as Type = Type.GetType(typeNameString);
// Make a new instance of the object.
Dim o as Object = Activator.CreateInstance(t);

C#:

// Get the type of object being deserialized.
Type t = Type.GetType(typeNameString);
// Make a new instance of the object.
object o = Activator.CreateInstance(t);

Edit (26 Oct, 2009, 15:10 GMT-0600): The Type.GetType(string typeNameString) method does not always recognize types as simply their fully qualified name. It would be in your best interest to be sure and include as much information as you can in your parameter string, as follows:

编辑(2009年10月26日,格林威治标准时间-0600 15:10):Type.GetType(字符串typeNameString)方法并不总是将类型识别为其完全限定名称。确保在参数字符串中包含尽可能多的信息符合您的最佳利益,如下所示:

VB.Net/C#:

typeNameString = objectSerialized.GetType().Namespace + ", " + objectSerialized.GetType().Name + ", " + objectSerialized.GetType().Assembly.FullName

Less specifically, I just had the same problem, and after a lot of research, I finally came up with a nice solution for handling all most of this dynamically. I've posted the entire source code to a class capable of serializing and deserializing objects of any type not containing generics or arrays using Reflection. Feel free to take it and use it as your own. If anyone decides to add the handling for generics and arrays, please send me an updated copy so I can post it back on my blog (and you'll get an honorable mention ;-)...). It will serialize everything recursively, and has some special coding in there for enums as well.

不太具体,我只是遇到了同样的问题,经过大量的研究,我终于提出了一个很好的解决方案来动态处理所有这些问题。我已经将整个源代码发布到一个类,该类能够使用Reflection对不包含泛型或数组的任何类型的对象进行序列化和反序列化。随意拿它并使用它作为你自己的。如果有人决定添加对泛型和数组的处理,请发给我一份更新的副本,这样我就可以将它发布回我的博客上(你会获得荣誉奖; - )......)。它会递归地序列化所有内容,并且还有一些特殊的编码用于枚举。

Take a look and see if that covers everything you're looking for at:

看一看,看看它是否涵盖了您正在寻找的一切:

http://maxaffinity.blogspot.com/2009/10/serialize-objects-manually.html

~md5sum~

Edit (27 Oct, 2009 14:38 GMT-0600): Corrected some misinformation about the class available from my blog.

编辑(2009年10月27日14:38 GMT-0600):纠正了我博客上有关课程的一些错误信息。

#1


Have you tried using Type.GetType? This takes a string parameter and returns a type for that name. You may have to give it additional information about the simple name "widget" and more along the lines of a full name. But it appears from your sample they should all have the same namespace so that shouldn't be a big hurdle.

你尝试过使用Type.GetType吗?这将获取一个字符串参数并返回该名称的类型。您可能需要提供有关简单名称“小部件”的更多信息以及更多全名的信息。但是从你的示例中看,它们应该都具有相同的命名空间,因此不应该是一个很大的障碍。

#2


The other option if you want an actual keyword Type to work with, and not a variable type is using something like (sorry I'm using C# and am too tired to do the VB conversion):

另一个选项,如果你想要一个实际的关键字Type使用,而不是一个变量类型使用类似的东西(对不起,我正在使用C#,我太累了,无法进行VB转换):

method in XmlSerializer like Deserialize(typestring, object);
method in XmlSerializer like Deserialize<T>(object);


public void Deserialize(string typestring, object obj)
{
  MethodInfo deserialize = typeof(XmlSerializer)
      .GetMethod("Deserialize", BindingFlags.Instance | BindingFlags.Public)
      .MakeGenericMethod(new Type[] { Type.GetType(typestring) });
  deserialize.Invoke(this, new[] { obj });
}

#3


Specifically, I think you're looking for this code here (NOTE: I don't work much in VB.Net, so I hope everything there is syntactically correct):

具体来说,我认为你在这里寻找这个代码(注意:我在VB.Net中工作不多,所以我希望所有语法都正确):

VB.Net:

// Get the type of object being deserialized.
Dim t as Type = Type.GetType(typeNameString);
// Make a new instance of the object.
Dim o as Object = Activator.CreateInstance(t);

C#:

// Get the type of object being deserialized.
Type t = Type.GetType(typeNameString);
// Make a new instance of the object.
object o = Activator.CreateInstance(t);

Edit (26 Oct, 2009, 15:10 GMT-0600): The Type.GetType(string typeNameString) method does not always recognize types as simply their fully qualified name. It would be in your best interest to be sure and include as much information as you can in your parameter string, as follows:

编辑(2009年10月26日,格林威治标准时间-0600 15:10):Type.GetType(字符串typeNameString)方法并不总是将类型识别为其完全限定名称。确保在参数字符串中包含尽可能多的信息符合您的最佳利益,如下所示:

VB.Net/C#:

typeNameString = objectSerialized.GetType().Namespace + ", " + objectSerialized.GetType().Name + ", " + objectSerialized.GetType().Assembly.FullName

Less specifically, I just had the same problem, and after a lot of research, I finally came up with a nice solution for handling all most of this dynamically. I've posted the entire source code to a class capable of serializing and deserializing objects of any type not containing generics or arrays using Reflection. Feel free to take it and use it as your own. If anyone decides to add the handling for generics and arrays, please send me an updated copy so I can post it back on my blog (and you'll get an honorable mention ;-)...). It will serialize everything recursively, and has some special coding in there for enums as well.

不太具体,我只是遇到了同样的问题,经过大量的研究,我终于提出了一个很好的解决方案来动态处理所有这些问题。我已经将整个源代码发布到一个类,该类能够使用Reflection对不包含泛型或数组的任何类型的对象进行序列化和反序列化。随意拿它并使用它作为你自己的。如果有人决定添加对泛型和数组的处理,请发给我一份更新的副本,这样我就可以将它发布回我的博客上(你会获得荣誉奖; - )......)。它会递归地序列化所有内容,并且还有一些特殊的编码用于枚举。

Take a look and see if that covers everything you're looking for at:

看一看,看看它是否涵盖了您正在寻找的一切:

http://maxaffinity.blogspot.com/2009/10/serialize-objects-manually.html

~md5sum~

Edit (27 Oct, 2009 14:38 GMT-0600): Corrected some misinformation about the class available from my blog.

编辑(2009年10月27日14:38 GMT-0600):纠正了我博客上有关课程的一些错误信息。