如何使用reflection找到特定的generics过载?

我正在尝试创建一个将调用特定generics重载方法的Expression (在我的第一个测试用例中为Enumerable.Average )。 特定类型绑定直到运行时才知道,因此我需要使用Reflection来查找和创建正确的generics方法( Expression是从解析后的文本创建的)。

所以,如果我在运行时知道我想找到这个特定的重载:

 public static double Average(this IEnumerable source, Func selector) 

如何使用reflection解析特定的MethodInfo

到目前为止,我有以下选择声明:

 MethodInfo GetMethod(Type argType, Type returnType) { var methods = from method in typeof(Enumerable).GetMethods(BindingFlags.Public | BindingFlags.Static) where method.Name == "Average" && method.ContainsGenericParameters && method.GetParameters().Length == 2 && // and some condition where method.GetParameters()[1] is a Func that returns type argType method.ReturnType == returnType select method; Debug.Assert(methods.Count() == 1); return methods.FirstOrDefault(); } 

上面将它缩小到三个重载,但我想反映并找到特定的重载,它采用Func ,其中argType == typeof(int)

我很难过,任何帮助都表示赞赏。

您需要使用MethodInfo.MakeGenericMethod

编辑:好的,我误解了这个问题……这个方法应该做你想要的:

 MethodInfo GetMethod(Type argType, Type returnType) { var enumerableType = typeof(IEnumerable<>).MakeGenericType(new Type[] { argType }); Console.WriteLine(enumerableType); var methods = from method in typeof(Enumerable).GetMethods(BindingFlags.Public | BindingFlags.Static) let parameters = method.GetParameters() let genParams = method.GetGenericArguments() where method.Name == "Average" && method.ContainsGenericParameters && parameters.Length == 2 && parameters[1].ParameterType.GetGenericTypeDefinition() == typeof(Func<,>) && parameters[1].ParameterType.GetGenericArguments()[1] == argType && method.ReturnType == returnType select method; return methods.FirstOrDefault(); } 

由于您正在构建表达式而不是直接执行,因此可以跳过MethodInfo步骤并使用Expression.Call重载直接进入MethodCallExpression,该重载采用方法名称而不是MethodInfo。

 var call = Expression.Call(typeof(Enumerable), "Average", new Type[] { typeof(MyTSource) }, enumerableParameter, lambdaParameter ); 

这是怎么做的:

 static MethodInfo GetMethod(Type argType, Type returnType) { var methods = from m in typeof(Enumerable).GetMethods(BindingFlags.Static | BindingFlags.Public) where m.ContainsGenericParameters && m.Name == "Average" && m.GetParameters()[1].ParameterType.GetGenericTypeDefinition() == typeof(Func<,>) && m.GetParameters()[1].ParameterType.GetGenericArguments()[1] == returnType select m; return methods.First(); } 

感谢@Joren的链接提示。 该示例根据参数计数区分,但它使我朝着正确的方向前进。

有效的选择是

 var methods = from method in typeof(Enumerable).GetMethods(BindingFlags.Public | BindingFlags.Static) where method.Name == Name && method.ContainsGenericParameters && method.ReturnType == returnType && method.GetParameters().Length == 2 && method.GetParameters()[1].ParameterType.GetGenericArguments().Count() == 2 && method.GetParameters()[1].ParameterType.GetGenericArguments()[1] == argType select method;