What Types should be in the Type array for Type.GetMethod when a parameter is generic?

前端 未结 2 1637
爱一瞬间的悲伤
爱一瞬间的悲伤 2021-01-24 01:09

If I want to call a generic method through reflection, I can easily use this technique, unless:

  1. The method can only be distinguished from another by its parameters
相关标签:
2条回答
  • 2021-01-24 01:44

    I'll give you the full "thing" I use when I have to find a Queryable.Select<TSource, TResult> Method (IQueryable<TSource>, Expression<Func<TSource, TResult>>) method... It is quite complex and checks nearly all:

    MethodInfo selectMethod = (from x in typeof(Queryable).GetMethods(BindingFlags.Static | BindingFlags.Public)
                               where x.Name == "Select" && x.IsGenericMethod
                               let pars = x.GetParameters()
                               where pars.Length == 2
                               let args = x.GetGenericArguments()
                               where args.Length == 2 &&
                                   pars[0].ParameterType == typeof(IQueryable<>).MakeGenericType(args[0]) &&
                                   pars[1].ParameterType == typeof(Expression<>).MakeGenericType(typeof(Func<,>).MakeGenericType(args))
                               select x).Single();
    

    You can easily use it as a template.

    Note that the return type isn't checked, because there is no overload for return types. The fact that the method is static and public is checked by the GetMethods(). I check number of parameters, number of generic arguments, type of parameters. Then I use the Single() to be sure that there is only one method. This should be future-proof: even if Microsoft added another Queryable.Select method, it would be "different".

    In your specific case:

    MethodInfo method = (from x in typeof(Example).GetMethods(BindingFlags.Instance | BindingFlags.Public)
                         where x.Name == "DoSomething" && x.IsGenericMethod
                         let pars = x.GetParameters()
                         where pars.Length == 1
                         let args = x.GetGenericArguments()
                         where args.Length == 1 &&
                             pars[0].ParameterType == args[0]
                         select x).Single();
    
    0 讨论(0)
  • 2021-01-24 01:46

    You could do something like this:

    MethodInfo method = typeof(Example)
        .GetMethods().First(mi => mi.Name == "DoSomething" && mi.IsGenericMethod);
    

    Depending on how many method overloads you have, you might have to make the predicate more specific.

    0 讨论(0)
提交回复
热议问题