如何正确替换泛型方法定义的System.Type[]中的泛型类型?
正确替换泛型方法定义中参数类型的泛型参数
直接调用Type.MakeGenericType会导致泛型参数映射错误,因为参数类型中的泛型参数属于方法自身的泛型定义参数,需要和传入的genericArguments按顺序一一对应,而非直接将参数类型当作泛型定义填充。
解决方案:递归替换泛型参数
实现一个工具方法,递归遍历类型结构,将方法定义中的泛型参数替换为传入的实际类型:
using System; using System.Linq; public static class GenericTypeResolver { public static Type ResolveGenericType(Type type, Type[] methodGenericParameters, Type[] actualGenericArguments) { // 处理方法定义的泛型参数(如TOne、TTwo) if (type.IsGenericParameter) { int paramIndex = Array.IndexOf(methodGenericParameters, type); return actualGenericArguments[paramIndex]; } // 处理泛型类型定义(如IDictionary<,>) if (type.IsGenericTypeDefinition) { Type[] resolvedArgs = type.GetGenericArguments() .Select(arg => ResolveGenericType(arg, methodGenericParameters, actualGenericArguments)) .ToArray(); return type.MakeGenericType(resolvedArgs); } // 处理已构造的泛型类型(如List<TOne>) if (type.IsGenericType && !type.IsGenericTypeDefinition) { Type genericDef = type.GetGenericTypeDefinition(); Type[] resolvedArgs = type.GetGenericArguments() .Select(arg => ResolveGenericType(arg, methodGenericParameters, actualGenericArguments)) .ToArray(); return genericDef.MakeGenericType(resolvedArgs); } // 非泛型类型直接返回 return type; } }
使用方式
- 获取泛型方法定义的自身泛型参数:
Type[] methodGenericParams = methodInfo.GetGenericArguments();
- 遍历原参数类型数组,逐个替换泛型参数:
Type[] resolvedTypes = types .Select(t => GenericTypeResolver.ResolveGenericType(t, methodGenericParams, genericArguments)) .ToArray();
验证测试用例
将上述代码应用到你的测试用例中:
// 原代码中获取未定义的类型数组后 Type[] types = ( from ParameterInfo parameter in methodInfo.GetParameters() select parameter.ParameterType ).ToArray(); // 替换泛型参数 Type[] resolvedTypes = types .Select(t => GenericTypeResolver.ResolveGenericType(t, methodInfo.GetGenericArguments(), genericArguments)) .ToArray(); // 输出结果 WriteLine(); WriteLine("----Resolved Generic Types:"); foreach (Type type in resolvedTypes) WriteLine(type); WriteLine("----End");
输出会和invokableMethodInfo获取的结果一致:System.String。
复杂场景验证
针对你提到的void MyGenericMethod<TOne, TTwo, TThree>(IDictionary<TOne, TThree> Dictionary):
- 方法泛型参数为
[TOne, TTwo, TThree] - 实际传入的
genericArguments为[typeof(int), typeof(string), typeof(DateTime)] - 替换后参数类型会正确变为
IDictionary<int, DateTime>,而非错误匹配的IDictionary<int, string>。
内容的提问来源于stack exchange,提问作者Brendan Lynn
相关产品推荐
相关产品推荐

