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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-06 14:45:37  来源:igfitidea点击:

Pass Type dynamically to <T>

c#genericslist

提问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小号如RolesUsers

now i can get the Typewithin the List<>like this

现在我可以得到TypeList<>像这样

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?

无论如何,我可以将任何方法传递genericTypesGetXML方法吗?

采纳答案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.

您可以根据需要添加类型参数以支持它,直到您到达某个确实知道实体类型是什么的地方。