如何显式指定参数类型查找IEnumerable<T>.ToList()并调用自定义类型
反射调用
Enumerable.ToList<T>()的问题解决 问题1:无法通过typeof(IEnumerable)找到ToList方法
Enumerable.ToList<T>()是针对**泛型接口IEnumerable<T>**的扩展方法,而非非泛型的IEnumerable。直接用typeof(IEnumerable)作为参数类型查找,自然匹配不到正确的方法。
要显式指定参数类型查找,需要先定位到泛型方法的定义:
// 筛选出接收IEnumerable<T>参数的ToList泛型方法定义 var toListMethodDef = typeof(Enumerable).GetMethods() .First(m => m.Name == "ToList" && m.GetParameters().Length == 1 && m.GetParameters()[0].ParameterType.GetGenericTypeDefinition() == typeof(IEnumerable<>));
如果确认ToList只有这一个泛型重载,也可以直接用typeof(Enumerable).GetMethod("ToList")拿到泛型方法定义,后续再指定具体类型参数。
问题2:调用ToList时的类型转换异常
报错的核心原因是:你给ToList指定的泛型参数是Table<TestData>(testDataITable.GetType()的结果),但ToList<T>需要的是IEnumerable<T>中的T——也就是TestData,而非容器本身的类型。
正确的做法是从testDataITable的类型中提取出它实现的IEnumerable<T>的泛型参数,再用这个参数构造ToList的泛型方法:
// 获取testDataITable实现的IEnumerable<T>接口 var enumerableType = testDataITable.GetType() .GetInterfaces() .First(i => i.IsGenericType && i.GetGenericTypeDefinition() == typeof(IEnumerable<>)); // 提取泛型参数TestData var elementType = enumerableType.GetGenericArguments()[0]; // 构造正确的ToList泛型方法 var toListGeneric = toListMethodDef.MakeGenericMethod(elementType); // 调用方法 var ret = toListGeneric.Invoke(null, new object[] { testDataITable });
完整修正后的Main方法代码
static void Main(string[] args) { var dataContext = new DataContext(); // 调用GetTable<TestData> var getTableMethod = typeof(DataExtensions).GetMethod("GetTable", new[] { typeof(IDataContext) }); var getTableGeneric = getTableMethod.MakeGenericMethod(typeof(TestData)); var testDataITable = getTableGeneric.Invoke(null, new object[] { dataContext }); // 获取ToList的泛型方法定义 var toListMethodDef = typeof(Enumerable).GetMethods() .First(m => m.Name == "ToList" && m.GetParameters().Length == 1 && m.GetParameters()[0].ParameterType.GetGenericTypeDefinition() == typeof(IEnumerable<>)); // 提取IEnumerable<T>的泛型参数TestData var enumerableType = testDataITable.GetType() .GetInterfaces() .First(i => i.IsGenericType && i.GetGenericTypeDefinition() == typeof(IEnumerable<>)); var elementType = enumerableType.GetGenericArguments()[0]; // 调用ToList<TestData> var toListGeneric = toListMethodDef.MakeGenericMethod(elementType); var ret = toListGeneric.Invoke(null, new object[] { testDataITable }); Console.ReadKey(); }
内容的提问来源于stack exchange,提问作者bairog
相关产品推荐
相关产品推荐

