C# 将类型动态传递给 <T>
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1292480/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Pass Type dynamically to <T>
提问by
See i have a situation like this...
看到我有这样的情况...
object myRoledata = List<Roles>() --> (some list or Ienumerable type)
Now i have a generic method which creates an XML object from List<T>-
Something like this..
现在我有一个通用的方法来创建一个 XML 对象List<T>- 像这样的东西..
public string GetXML<T>(object listdata)
{
List<T> objLists = (List<T>)Convert.ChangeType(listData, typeof(List<T>));
foreach(var obj in listdata)
{
//logic to create xml
}
}
Now in order to run this method I have to do like this:
现在为了运行这个方法,我必须这样做:
string xml = GetXML<Roles>(myRoledata);
Now i dont know what Typemay come to me to be passed to GetXMLmethod. I have a method which will call GetXMLfor different Types e.g. Roles, Usersetc
现在我不知道什么Type可能会传递给我GetXML。我有这将调用一个方法GetXML针对不同的Type小号如Roles,Users等
now i can get the Typewithin the List<>like this
现在我可以得到Type内List<>像这样
Type genericType = obj.GetType().GetGenericArguments()[0];
but cannot pass it like this
但不能像这样通过
string xml = GetXML<genericType>(myRoledata);
Is there anyway in which i can pass any genericTypesto GetXMLmethod?
无论如何,我可以将任何方法传递genericTypes给GetXML方法吗?
采纳答案by Eamon Nerbonne
This is a problem you probably want to avoidsolving. It ispossible, via reflection, to call methods dynamically without statically resolving them - but it kind of defeats the whole point of the type-annotations.
这是您可能想要避免解决的问题。这是可能的,通过反射,动态调用方法,而静态地解决这些问题-但它那种失败的类型注释的整点。
Either do this:
要么这样做:
public string GetXML(IEnumerable listdata) {
foreach(object obj in listdata)
//logic to create xml
}
... which you now can call with any IEnumerable, or write it the "modern" way as:
...您现在可以使用 any 调用IEnumerable它,或者以“现代”方式将其写为:
public string GetXML(IEnumerable<object> listdata) {
foreach(object obj in listdata)
//logic to create xml
}
... which you can call with any IEnumerablevia GetXML(someEnumerable.Cast<object>())and in C# 4.0 even directly by covariance.
...您可以使用任何IEnumerableviaGetXML(someEnumerable.Cast<object>())和 C# 4.0 甚至直接通过协方差调用。
If you need the type of an element runtime, you can get it using .GetType()on each element, or you can just pass it in as a parameter (and provide an override for backwards-compatibility):
如果您需要元素运行时的类型,您可以.GetType()在每个元素上使用它,或者您可以将它作为参数传入(并提供向后兼容性的覆盖):
public string GetXML(Type elementType, IEnumerable<object> listdata) {
foreach(object obj in listdata)
//logic to create xml
}
public string GetXML<T>(IEnumerable<T> listdata) {
return GetXML(typeof(T),listdata.Cast<object>());
}
Incidentally, if you're constructing XML, a string is probably a less robust return-type choice: if possible, you could work with something like an XElementinstead - and get xml-validity guarantee's to boot.
顺便说一句,如果您正在构建 XML,则字符串可能是一个不太可靠的返回类型选择:如果可能,您可以使用类似 an 的东西XElement来代替 - 并获得 xml-validity 保证的启动。
回答by Marc Gravell
To do that, you need to use reflection;
为此,您需要使用反射;
typeof(SomeClass).GetMethod("GetXML").MakeGenericMethod(genericType)
.Invoke(inst, new object[] {myRoleData});
where instis nullif it is a static method, thisfor the current instance (in which case you can also use GetType()instead of typeof(SomeClass)), or the target object otherwise.
where instisnull如果它是一个静态方法,则this用于当前实例(在这种情况下,您也可以使用GetType()代替typeof(SomeClass)),否则为目标对象。
回答by Ulrik Rasmussen
Since you cast your listdata parameter as a List< T> in the first line of your method, why don't you just change the method signature to
既然您在方法的第一行将 listdata 参数转换为 List< T> ,为什么不将方法签名更改为
public string GetXML<T>(List<T> listdata)
That way, you don't have to use reflection to get the generic arguments.
这样,您就不必使用反射来获取通用参数。
EDIT: I see that you need to be able to accept IEnumerable collections, and not just lists. So, consider changing your method signature to
编辑:我看到您需要能够接受 IEnumerable 集合,而不仅仅是列表。因此,请考虑将您的方法签名更改为
public string GetXML<T>(IEnumerable<T> listdata)
回答by Achim
You have the right idea, but you are using the wrong method. Have a look at Type.MakeGenericType or MethodInfo.MakeGenericMethod. It will take a few more lines than your example, but it should be simple to solve.
你有正确的想法,但你使用了错误的方法。看看 Type.MakeGenericType 或 MethodInfo.MakeGenericMethod。它将比您的示例多几行,但解决起来应该很简单。
GetGenericArguments() can be used to get the Roles type from a List. It's the differnt way around.
GetGenericArguments() 可用于从列表中获取角色类型。这是不同的方式。
Btw: Looks like your implementing some kind of XML serialization. Make sure you check existing classes, before reinventing the wheel. ;-)
顺便说一句:看起来您实现了某种 XML 序列化。在重新发明轮子之前,请确保检查现有类。;-)
回答by Matthew Scharley
I don't know your situation, but is it possible to rewrite your function as:
我不知道您的情况,但是否可以将您的函数重写为:
public string GetXML<T>(IEnumerable<T> listdata)
{
foreach(var obj in listdata)
{
//logic to create xml
}
}
Then it can be called as:
那么它可以被称为:
List<Role> myList;
GetXML(myList);
You can add type parameters as far back as needed to support it, till you get to somewhere that does know what the solid type is.
您可以根据需要添加类型参数以支持它,直到您到达某个确实知道实体类型是什么的地方。

