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 Type
may come to me to be passed to GetXML
method. I have a method which will call GetXML
for different Type
s e.g. Roles
, Users
etc
现在我不知道什么Type
可能会传递给我GetXML
。我有这将调用一个方法GetXML
针对不同的Type
小号如Roles
,Users
等
now i can get the Type
within 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 genericTypes
to GetXML
method?
无论如何,我可以将任何方法传递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 IEnumerable
via GetXML(someEnumerable.Cast<object>())
and in C# 4.0 even directly by covariance.
...您可以使用任何IEnumerable
viaGetXML(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 XElement
instead - 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 inst
is null
if it is a static method, this
for the current instance (in which case you can also use GetType()
instead of typeof(SomeClass)
), or the target object otherwise.
where inst
isnull
如果它是一个静态方法,则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.
您可以根据需要添加类型参数以支持它,直到您到达某个确实知道实体类型是什么的地方。