How to I find specific generic overload using reflection?

别说谁变了你拦得住时间么 提交于 2019-12-01 04:20:13

问题


I am attempting to create an Expression that will invoke a specific generic overloaded method (Enumerable.Average in my first test case). The specific type bindings are not known until runtime however so I need to use Reflection to find and create the correct generic method (the Expression is being created from parsed text).

So if I know at runtime that I want to find this specific overload:

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

How do I resolve that particular MethodInfo using reflection?

So far I have the following selection statement:

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

The above narrows it down to three overloads but I want to reflect and find the specific overload that takes a Func<TSource, int> where argType == typeof(int).

I am stumped and any help is appreciated.


回答1:


You need to use MethodInfo.MakeGenericMethod

EDIT: OK, I had misunderstood the problem... This method should do what you want :

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



回答2:


Since you're building an expression rather than executing directly, you can skip the MethodInfo step and go straight to the MethodCallExpression using the Expression.Call overload that takes a method name rather than a MethodInfo.

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



回答3:


Here's how to do it:

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



回答4:


Thanks @Joren for the linked hint. That example differentiates based on argument count to but it got me in the right direction.

The selection that works is

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;


来源:https://stackoverflow.com/questions/1465715/how-to-i-find-specific-generic-overload-using-reflection

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!