C#反射:获取含多泛型重载的静态方法并运行时指定参数
反射获取多泛型重载静态方法并结合运行时泛型参数使用
核心步骤
要搞定Tuple.Create这类多泛型重载的静态方法,且泛型参数仅运行时已知的场景,分这几步走:
1. 定位目标类型的所有候选方法
先拿到包含目标方法的类型,比如typeof(Tuple),然后筛选出所有名为Create的静态泛型方法:
var tupleType = typeof(Tuple); var createMethods = tupleType.GetMethods(BindingFlags.Public | BindingFlags.Static) .Where(m => m.Name == "Create" && m.IsGenericMethodDefinition) .ToList();
2. 匹配对应泛型参数数量的重载
Tuple.Create有从1元到8元的泛型重载,根据你需要的泛型参数个数,找到对应的方法定义。比如要创建2元组,就找有2个泛型参数的重载:
int genericArgCount = 2; // 这个数值可由运行时逻辑动态确定 var targetMethod = createMethods.First(m => m.GetGenericArguments().Length == genericArgCount);
3. 绑定运行时泛型参数
把运行时获取的类型参数绑定到泛型方法定义上,得到可直接调用的MethodInfo:
// 假设这两个类型是运行时动态获取的(比如从配置、反射其他类型得到) Type type1 = typeof(string); Type type2 = typeof(int); var constructedMethod = targetMethod.MakeGenericMethod(type1, type2);
4. 调用构造好的方法
传入对应参数,执行方法得到结果:
object result = constructedMethod.Invoke(null, new object[] { "test", 123 }); // result 即为 Tuple<string, int> 实例
结合自定义泛型类型的场景
如果要和自定义泛型类型结合使用,比如你有个MyGeneric<T>,需要把创建好的Tuple作为泛型参数传入,或者调用自定义泛型方法,以下是两种常见场景:
场景1:创建自定义泛型实例并传入Tuple
假设自定义泛型类:
public class MyGeneric<T> { public void Process(T value) { Console.WriteLine($"Processing content: {value}"); } }
运行时绑定泛型类型并调用方法:
// 先通过反射创建Tuple实例(复用前面的逻辑) object tupleInstance = constructedMethod.Invoke(null, new object[] { "test", 123 }); Type tupleActualType = tupleInstance.GetType(); // 绑定自定义泛型类型 var myGenericType = typeof(MyGeneric<>).MakeGenericType(tupleActualType); object myGenericInstance = Activator.CreateInstance(myGenericType); // 获取并调用Process方法 var processMethod = myGenericType.GetMethod("Process"); processMethod.Invoke(myGenericInstance, new object[] { tupleInstance });
场景2:直接联动泛型参数调用自定义泛型方法
如果自定义类有个泛型方法需要和Tuple的泛型参数联动:
public class MyHelper { public static void HandleTuple<T1, T2>(Tuple<T1, T2> tuple) { Console.WriteLine($"Item1: {tuple.Item1}, Item2: {tuple.Item2}"); } }
运行时绑定泛型参数并调用:
Type[] tupleTypes = new[] { typeof(string), typeof(int) }; var handleMethod = typeof(MyHelper).GetMethod("HandleTuple") .MakeGenericMethod(tupleTypes); // 先创建Tuple实例 object tuple = constructedMethod.Invoke(null, new object[] { "hello", 456 }); handleMethod.Invoke(null, new object[] { tuple });
注意事项
- 如果自定义方法存在泛型参数数量相同但参数类型不同的重载,需要额外筛选方法的参数类型来精准匹配
- 调用
Invoke时,静态方法的第一个参数传null,实例方法需传入对应实例对象 - 运行时类型转换要注意安全,必要时用
is或as关键字做类型校验
内容的提问来源于stack exchange,提问作者Mansoor Omrani
相关产品推荐
相关产品推荐

