-->

如何使用我发现反射特定通用超载?(How to I find specific generic ov

2019-07-19 03:31发布

我试图创建一个Expression ,将调用一个特定的通用重载的方法( Enumerable.Average在我的第一个测试案例)。 具体类型绑定直到运行时才知道不过,所以我需要使用Reflection来查找和创建正确的泛型方法(在Expression正在从分析的文本创建)。

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

public static double Average<TSource>(this IEnumerable<TSource> source, Func<TSource, int> selector)

如何解决特定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<TSource, int>其中argType == typeof(int)

我难倒任何帮助表示赞赏。

Answer 1:

您需要使用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();
}


Answer 2:

既然你正在构建的表达,而不是直接执行,你可以跳过MethodInfo的步骤,并且使用Expression.Call重载需要一个方法的名称,而不是一个MethodInfo直奔MethodCallExpression。

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


Answer 3:

以下是如何做到这一点:

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();
}


Answer 4:

感谢@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;


文章来源: How to I find specific generic overload using reflection?