将类型动态传递给<t> </t>

时间:2009-08-18 08:12:49

标签: c# generics list

看到我有这样的情况......

object myRoledata  = List<Roles>() --> (some list or Ienumerable type)

现在我有一个从List<T>创建XML对象的通用方法 - 像这样......

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  
    }  
}

现在为了运行这个方法,我必须这样做:

string xml = GetXML<Roles>(myRoledata);

现在我不知道Type可能会传给GetXML方法。我有一种方法可以针对不同的GetXML调用Type,例如RolesUsers

现在我可以像Type一样获得List<>

Type genericType = obj.GetType().GetGenericArguments()[0];

但不能像这样传递

string xml = GetXML<genericType>(myRoledata);

无论如何我可以通过任何genericTypesGetXML方法吗?

5 个答案:

答案 0 :(得分:8)

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

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

其中instnull如果是静态方法,this为当前实例(在这种情况下,您也可以使用GetType()代替typeof(SomeClass) }),否则就是目标对象。

答案 1 :(得分:7)

由于您将listdata参数转换为List&lt; T&GT;在方法的第一行,为什么不将方法签名更改为

public string GetXML<T>(List<T> listdata)

这样,您就不必使用反射来获取通用参数。

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

public string GetXML<T>(IEnumerable<T> listdata)

答案 2 :(得分:2)

我不知道你的情况,但可以将你的功能重写为:

public string GetXML<T>(IEnumerable<T> listdata)  
{  
    foreach(var obj in listdata)   
    {  
        //logic to create xml  
    }  
}

然后它可以被称为:

List<Role> myList;
GetXML(myList);

您可以根据需要添加类型参数以支持它,直到您到达确实知道固体类型的位置。

答案 3 :(得分:2)

这是您可能希望避免解决的问题。 可以通过反射来动态地调用方法而不用静态地解析它们 - 但它有点打败了类型注释的全部要点。

要么这样做:

public string GetXML(IEnumerable listdata) {  
    foreach(object obj in listdata)   
        //logic to create xml  
}

...您现在可以使用任何IEnumerable调用,或者将其写为“现代”方式:

public string GetXML(IEnumerable<object> listdata) {  
    foreach(object obj in listdata)   
        //logic to create xml  
}

...您可以使用任何IEnumerable通过GetXML(someEnumerable.Cast<object>())和C#4.0直接通过协方差调用。

如果您需要元素运行时的类型,可以在每个元素上使用.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>());
}

顺便提一下,如果你正在构建XML,那么字符串可能是一个不太健壮的返回类型选择:如果可能的话,你可以使用类似XElement的东西 - 并获得启动xml-validity保证。

答案 4 :(得分:0)

你有正确的想法,但你使用的是错误的方法。看看Type.MakeGenericType或MethodInfo.MakeGenericMethod。它将比你的例子多几行,但它应该很容易解决。

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

顺便说一句:看起来你正在实现某种XML序列化。在重新发明轮子之前,请确保检查现有的类。 ; - )