假设我们有以下代码(对我自己的代码进行了高度简化的修改):
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
namespace ReflectionTest
{
public interface IDataContext
{ }
sealed class DataContext : IDataContext
{ }
public interface ITable<T> : IEnumerable<T>
where T : class
{
List<T> source { get; }
}
sealed class Table<T> : ITable<T>
where T : class, new()
{
public Table()
{
source = new List<T>() { new T() };
}
public List<T> source { get; set; }
public IEnumerator<T> GetEnumerator() => source.GetEnumerator();
IEnumerator IEnumerable.GetEnumerator() => source.GetEnumerator();
}
public static class DataExtensions
{
public static ITable<T> GetTable<T>(this IDataContext dataContext)
where T : class, new()
{
return new Table<T>();
}
}
public class TestData
{
public string Name = "Test";
}
internal class Program
{
static void Main(string[] args)
{
var dataContext = new DataContext();
//var ret = dataContext.GetTable<TestData>().ToList(); but via reflection:
var getTableMethod = typeof(DataExtensions).GetMethod("GetTable", new[] { typeof(IDataContext) });
var getTableGeneric = getTableMethod.MakeGenericMethod(typeof(TestData));
var testDataITable = getTableGeneric.Invoke(null, new object[] { dataContext });
//var toListMethod = typeof(Enumerable).GetMethod("ToList", new[] { typeof(IEnumerable) }); this doesn't find IEnumerable<T>.ToList() method!
var toListMethod = typeof(Enumerable).GetMethod("ToList");
var toListGeneriс = toListMethod.MakeGenericMethod(testDataITable.GetType());
//System.ArgumentException: 'Unable to cast object of type "ReflectionTest.Table`1[ReflectionTest.TestData]"
//to type "System.Collections.Generic.IEnumerable`1[ReflectionTest.Table`1[ReflectionTest.TestData]]".'
var ret = toListGeneriс.Invoke(null, new object[] { testDataITable });
Console.ReadKey();
}
}
}
我试图通过反射来调用
var ret = dataContext.GetTable<TestData>().ToList();
。我这里有两个问题:
typeof(Enumerable).GetMethod("ToList", new[] { typeof(IEnumerable) });
找不到 IEnumerable.ToList() 方法。我知道这种方法只有一个版本,我可以简单地使用 typeof(Enumerable).GetMethod("ToList");
- 但是,如何通过显式指定参数类型来找到它?ITable<TestData>
参数类型正确调用此方法?使用我的代码我得到一个例外:System.ArgumentException:'无法转换类型的对象 “ReflectionTest.Table
1[ReflectionTest.Table`1[ReflectionTest.TestData]]1[ReflectionTest.TestData]" to type System.Collections.Generic.IEnumerable
谢谢你。
Type.MakeGenericMethodParameter
创建一个“类型参数”,并使用它来创建代表 Type
的 IEnumerable<TSource>
。将其传递给 GetMethod
将为您提供所需的方法。
var typeVariable = Type.MakeGenericMethodParameter(0);
var parameterType = typeof(IEnumerable<>).MakeGenericType(typeVariable)
var toListMethod = typeof(Enumerable).GetMethod("ToList", [parameterType]);
对于第二个问题,是因为你参数化
ToList
不正确。您应该使用集合的元素类型 - TestData
:
var toListGeneriс = toListMethod.MakeGenericMethod(typeof(TestData));