在C#中,如何在运行时使用反射调用ToList()方法?

4

我有一个如下的通用类。

public class PaginatedList<T> : List<T>
{...}

我希望能够在运行时使用反射调用对象上的ToList()方法。 请问有人能提供帮助吗? 我已经做到这一步了。
MethodInfo toListMethod = typeof(Enumerable).GetMethod("ToList");
var constructedToList = toListMethod.MakeGenericMethod(TypeObjectOfT);
constructedToList.Invoke(paginatedListObject, null);

在最后一行我遇到了异常,错误信息为参数数量不匹配。根据toListMethod.ToString()constructedToList.ToString()的输出结果,我认为前两步是正确的。

System.Collections.Generic.List`1[TSource] ToList[TSource](System.Collections.Generic.IEnumerable`1[TSource])
System.Collections.Generic.List`1[AvbhHis.BL.Entities.PatientCategory] ToList[PatientCategory](System.Collections.Generic.IEnumerable`1[AvbhHis.BL.Entities.PatientCategory])

问题: 1. 到目前为止,我是正确的吗?

  1. MakeGenericMethod() 方法的参数应该是什么?在我的情况下,它应该是类型T的对象实例在运行时的类型。

  2. 调用 Invoke 方法似乎存在问题。将 null 作为第二个参数传递是否正确?第一个参数应该是 PaginatedList 类型的对象才对吧?

我的精力已经耗尽,请帮忙。


@Hani,你有点困惑:Enumerable是一个包含IEnumerable<T>扩展方法的类。此外,msdn说_Enumerable确实有ToList()_ - Grundy
混合使用泛型和反射通常是代码异味 - 在您的情况下是否没有一种以通用方式调用 ToList 的方法? - D Stanley
@Grundy 你有点困惑了 - OP 正在通过反射调用 Enumerable 上的 ToList - D Stanley
@DStanley,是的 :-) 可能我没有完全理解之前Hani的评论 :-) - Grundy
重点是ToList是一个扩展方法,而不是IEnumerable上的方法。它是一个静态方法,在扩展类上,以IENumerable作为其第一个参数。 - pm100
2个回答

7

第一个参数【传递给Invoke方法】应该是PaginatedList类型的对象,对吗?

ToListEnumerable类上的静态方法,它只有一个参数,即IEnumerable<T>

public static List<TSource> ToList<TSource>(
    this IEnumerable<TSource> source
)

Invoke 命令需要在第一个参数中传入 实例,而方法参数则在其之后。对于静态方法,您需要在 "实例" 参数中使用 null

因此,正确的语法应该是:

object o = constructedToList.Invoke(null, new object[] {paginatedListObject});

o将会是一个类型为List<T>的对象(但你在编译时不知道T是什么,所以无法强制转换它)。


我现在在调用过程中遇到了这个异常。"System.Reflection.MethodBase.Invoke(object, object[])的最佳重载方法匹配有一些无效参数"。 - VivekDev
@DumbDev 现在试试吧 - 我忘了 Invoke 不使用 params,所以第二个参数必须作为数组传递。 - D Stanley
谢谢你,Stanley。现在它完美地工作了。既然我只能选择一个,我会毫不犹豫地选择你的建议。 - VivekDev

2

List<T>有一个构造函数,它以IEnumerable<T>为参数(在ToList中调用),因此您可以通过编写以下内容来简化此任务:

    var resul = Activator.CreateInstance(typeof(List<>).MakeGenericType(TypeObjectOfT), paginatedListObject);

这也是一个可爱的答案。 - VivekDev
使泛型类型以数组作为第一个参数。.MakeGenericType(new Type[] { TypeObjectOfT }) - Bojidar Stanchev
@BojidarStanchev 是正确的,但它有 params 关键字,因此您不需要声明数组。 - CSharpie

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接