C# 将类型动态传递到<;T>;

C# 将类型动态传递到<;T>;,c#,generics,list,C#,Generics,List,看,我遇到了这样的情况 object myRoledata = List<Roles>() --> (some list or Ienumerable type) 但是不能这样通过 Type genericType = obj.GetType().GetGenericArguments()[0]; string xml = GetXML<genericType>(myRoledata); stringxml=GetXML(myRoledata); 我是否可

看,我遇到了这样的情况

object myRoledata  = List<Roles>() --> (some list or Ienumerable type)
但是不能这样通过

Type genericType = obj.GetType().GetGenericArguments()[0];
string xml = GetXML<genericType>(myRoledata);
stringxml=GetXML(myRoledata);

我是否可以将任何
泛型
传递给
GetXML
方法?

要做到这一点,需要使用反射

typeof(SomeClass).GetMethod("GetXML").MakeGenericMethod(genericType)
         .Invoke(inst, new object[] {myRoleData});

其中,
inst
null
如果它是一个静态方法,
这个
用于当前实例(在这种情况下,您也可以使用
GetType()
而不是
typeof(SomeClass)
),或者使用目标对象。

因为您在方法的第一行将listdata参数转换为列表,为什么不把方法签名改成

public string GetXML<T>(List<T> listdata)
public string GetXML<T>(IEnumerable<T> listdata)
公共字符串GetXML(列表listdata)
这样,您就不必使用反射来获取泛型参数

编辑:我发现您需要能够接受IEnumerable集合,而不仅仅是列表。因此,请考虑将方法签名更改为

public string GetXML<T>(List<T> listdata)
public string GetXML<T>(IEnumerable<T> listdata)
公共字符串GetXML(IEnumerable listdata)

您的想法是正确的,但使用的方法是错误的。查看Type.MakeGenericType或MethodInfo.MakeGenericMethod。这将比您的示例多出几行,但解决起来应该很简单

GetGenericArguments()可用于从列表中获取角色类型。这是不同的方式


顺便说一句:看起来您实现了某种XML序列化。在重新创建控制盘之前,请确保检查现有类。;-)

我不知道您的情况,但是否可以将您的函数重写为:

public string GetXML<T>(IEnumerable<T> listdata)  
{  
    foreach(var obj in listdata)   
    {  
        //logic to create xml  
    }  
}
公共字符串GetXML(IEnumerable listdata)
{  
foreach(listdata中的var obj)
{  
//创建xml的逻辑
}  
}
那么它可以被称为:

List<Role> myList;
GetXML(myList);
列出myList;
GetXML(myList);

您可以根据需要尽可能早地添加类型参数以支持它,直到您找到一个确实知道实体类型的地方。

这是一个您可能希望避免解决的问题。通过反射,可以在不静态解析方法的情况下动态调用方法,但这有点违背了类型注释的全部要点

要么这样做:

public string GetXML(IEnumerable listdata) {  
    foreach(object obj in listdata)   
        //logic to create xml  
}
。。。现在,您可以使用任何
IEnumerable
调用它,或以“现代”方式将其编写为:


顺便说一句,如果您正在构造XML,字符串可能是一种不太健壮的返回类型选择:如果可能,您可以使用类似于
XElement
的东西,然后启动XML有效性保证。

但这从根本上说不是错的吗?通过以这种方式调用该方法,实际上根本没有理由使用泛型,因为您放弃了类型检查,并在运行时获得所有错误。我对这个问题的解释是,他们希望将其与泛型解耦。如果这种解释不正确,那么你的方法显然更合适。这取决于情景-p如果类是static?@demoave,那么inst是null。您可能想在问题中弄清楚T的(可能有多种)类型在编译时是否未知。如果它们是已知的,那么Ulrik的答案是有意义的,即停止强制转换并强制参数类型(可能有几个重载)。若你们不知道,你们必须以某种形式使用反射,答案显示了实现这一点的最简单和可能最好的方法。事实上,我建议不要直接使用
IEnumerable
,至少在C#4.0;由于类型参数中缺少差异,它很可能不会执行您希望它执行的操作
IEnumerable
非常有用。特别是对于IEnumerable,由于Linq
.Cast
运算符,协方差问题不大。如果要使用
IEnumerable
参数调用方法,并且有一个
IEnumerable myEnum
和一些
T!=对象
,只需执行myEnum.Cast(),可读性和速度损失很小。非通用的
IEnumerable
在风格上的缺点是缺乏明确的
IDisposable
支持,
System.Collections
不是VS.NET添加到新文件中的默认用法,而且它是一种不太常见的习惯用法。无论如何,感谢您的评论-非泛型
IEnumerable
也是一个不错的选择。
public string GetXML(IEnumerable<object> listdata) {  
    foreach(object obj in listdata)   
        //logic to create xml  
}
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>());
}