How to get MethodInfo of a generic method on a non generic .NET type? [duplicate]
Asked Answered
D

2

9

I have this little problem, that I cannot figure out which arguments to pass to Type.GetMethod in order to get back the MethodInfo of a generic method on a non generic type. Specifically, I have this type definition:

public static class A
{
  public static B F<T>(bool dummy)
  {
  }
  public static B F<T>(IEnumerable<T> arg)
  {
  ...
  }
}

I have tried several takes at Type.GetMethod, but none would return the MethodInfo of the F method.

I am aware that I can invoke Type.GetMethods or even Type.FindMember, but I am interested in Type.GetMethod.

Any ideas?

Thanks.

EDIT

Actually, my code is a bit more complex. The generic method is overloaded, so I cannot use the Type.GetMethod with just the function name. I tried these variants:

typeof(A).GetMethod("F", BindingFlags.Static | BindingFlags.Public, null, new Type[]{ typeof(IEnumerable<>) }, null)
typeof(A).GetMethod("F`1", BindingFlags.Static | BindingFlags.Public, null, new Type[]{ typeof(IEnumerable<>) }, null)
typeof(A).GetMethod("F[T]", BindingFlags.Static | BindingFlags.Public, null, new Type[]{ typeof(IEnumerable<>) }, null)
typeof(A).GetMethod("F[[T]]", BindingFlags.Static | BindingFlags.Public, null, new Type[]{ typeof(IEnumerable<>) }, null)
Disenthrall answered 26/10, 2009 at 13:33 Comment(0)
P
9

The problem is that the IEnumerable<> parameter you are passing to GetMethod is not specialized. It really is an IEnumerable<T>, where T is specified by the method you are trying to retrieve. But, we can't get T via MethodInfo.GetGenericArguments() since we don't have a reference to the method -- we are still trying to retrieve it.

Unfortunately, this is where the reflection API falls short. There is no Type.GetMethod() overload that allows you to distinguish between overloaded methods, where one is a generic method.

So with that said, you are stuck using Type.GetMethods() and filtering the results with a predicate of your choice. To get the method you are interested in, you can do the following.

void getMethod()
{
    typeof(A).GetMethods().Where(m =>
        m.IsGenericMethod &&
        m.GetParameters()[0].ParameterType.GetGenericTypeDefinition()
            == typeof(IEnumerable<>));
}

N.B. I haven't verified that the GetGenericTypeDefinition() call is required; you may be able to omit it. The idea is that you are transforming a type A<T> into A<>, but the runtime may already give it to you in that form.

Pembrook answered 26/10, 2009 at 14:19 Comment(0)
H
6

(Updated in response to question clarifications):

There is no way to get a handle to the method using GetMethod (eg. one line), because the generic data to define the method isn't available until we have the method to inspect.

MethodInfo[] methods = typeof(A).GetMethods(BindingFlags.Static | BindingFlags.Public);
MethodInfo genericMethod = methods.Where(m=>m.IsGenericMethod).First(m=>m.ContainsGenericParameters);
genericMethod = genericMethod.GetGenericMethodDefinition();
  1. Get the methods
  2. Find the method that has generic parameters (assuming you only have one - if you add more than one, this needs to be a little more robust)
  3. Get the generic methodinfo
Heartily answered 26/10, 2009 at 13:36 Comment(3)
Thanks, but I have slighly misled in the question. I have changed it to be more accurate.Disenthrall
Thank you, but as I mention in my question I do know how to do it with GetMethods or FindMember. I am specifically interested in GetMethod, because it should do the job as well, but it does not and that bothers me.Disenthrall
@Mark there is no way to do it, because the generic data to define the method isn't available until we have the method to inspect.Heartily

© 2022 - 2024 — McMap. All rights reserved.