将Type动态传递给<T>

8 c# generics list

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

object myRoledata  = List<Roles>() --> (some list or Ienumerable type)
Run Code Online (Sandbox Code Playgroud)

现在我有一个通用的方法,可以创建一个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  
    }  
}
Run Code Online (Sandbox Code Playgroud)

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

string xml = GetXML<Roles>(myRoledata);
Run Code Online (Sandbox Code Playgroud)

现在我不知道Type可能会传给我的GetXML方法.我有一个方法,可以调用GetXML不同Type的例如Roles,Users等等

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

Type genericType = obj.GetType().GetGenericArguments()[0];
Run Code Online (Sandbox Code Playgroud)

但不能像这样传递它

string xml = GetXML<genericType>(myRoledata);
Run Code Online (Sandbox Code Playgroud)

反正有我在其中可以通过任何genericTypesGetXML方法?

Mar*_*ell 8

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

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

其中instnull如果它是一个静态方法,this对于当前实例(在这种情况下也可以使用GetType()的代替typeof(SomeClass)),或者目标对象物.

  • 但这不是根本错误吗?通过这种方式调用方法,根本没有理由使用泛型,因为您丢弃了类型检查,并在运行时获取所有错误. (2认同)
  • 我对这个问题的理解是,他们希望将其与泛型脱钩。如果这种解释不正确,那么您的方法显然更合适。这取决于场景;-p (2认同)

Ulr*_*sen 7

由于您在方法的第一行中将listdata参数转换为List <T>,为什么不将方法签名更改为

public string GetXML<T>(List<T> listdata)
Run Code Online (Sandbox Code Playgroud)

这样,您不必使用反射来获取泛型参数.

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

public string GetXML<T>(IEnumerable<T> listdata)
Run Code Online (Sandbox Code Playgroud)


Eam*_*nne 2

这是您可能想避免解决的问题。通过反射,可以动态调用方法而无需静态解析它们 - 但这有点违背了类型注释的全部意义。

要么这样做:

public string GetXML(IEnumerable listdata) {  
    foreach(object obj in listdata)   
        //logic to create xml  
}
Run Code Online (Sandbox Code Playgroud)

...您现在可以使用 any 来调用它IEnumerable,或者以“现代”方式编写它:

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

...您可以使用任何IEnumerablevia来调用它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>());
}
Run Code Online (Sandbox Code Playgroud)

顺便说一句,如果您正在构建 XML,则字符串可能是一个不太健壮的返回类型选择:如果可能,您可以使用类似XElement- 的东西来启动,并获得 xml 有效性保证。