Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Retrieving the MethodInfo of of the correct overload of a generic method

I have this type that contains two overloads of a generic method. I like to retrieve one of the overloads (with the Func<T> parameter) using reflection. The problem however is that I can't find the correct parameter type to supply the Type.GetMethod(string, Type[]) method with.

Here is my class definition:

public class Foo
{
    public void Bar<T>(Func<T> f) { }
    public void Bar<T>(Action<T> a) { }
}

And this is what I've come up with, unfortunately without succes:

[TestMethod]
public void Test1()
{
    Type parameterType = typeof(Func<>);

    var method = typeof(Foo).GetMethod("Bar", new Type[] { parameterType });

    Assert.IsNotNull(method); // Fails
}

How can I get the MethodInfo of a generic method of which I know the parameters?

like image 623
Anne Avatar asked Dec 14 '10 19:12

Anne


People also ask

How can generic method be overloaded?

A generic method may be overloaded like any other method. A class can provide two or more generic methods that specify the same method name but different method parameters. For example, generic method printArray of Fig.

Can we overload a generic method in C#?

Answer: Yes, we can overload a generic methods in C# as we overload a normal method in a class. Q- If we overload generic method in C# with specific data type which one would get called? Answer: Function with specific data type i.e int will be called.

Can we overload method in Web API?

Method overloading can be done in a web service with the following things: By changing the number of parameters used. By changing the order of parameters. By using different data types for the parameters.


2 Answers

Why don't you use expression trees? This makes it much easier:

public static MethodInfo GetMethod<T>(
    Expression<Action<T>> methodSelector)
{
    var body = (MethodCallExpression)methodSelector.Body;
    return body.Method;      
}

[TestMethod]
public void Test1()
{
    var expectedMethod = typeof(Foo)
        .GetMethod("Bar", new Type[] { typeof(Func<>) });

    var actualMethod = 
        GetMethod<Foo>(foo => foo.Bar<object>((Func<object>)null)
        .GetGenericMethodDefinition();

    Assert.AreEqual(expectedMethod, actualMethod);
}
like image 149
Steven Avatar answered Sep 29 '22 12:09

Steven


Surprisingly, it looks like you'll need to call GetMethods() and loop over the methods until you find the one you want.

For example:

var yourMethod = typeof(Foo).GetMethods()
    .First(m => m.Name == "Bar" 
             && m.GetParameters().Length == 1
             && m.GetParameters()[0].ParameterType.ContainsGenericParameters
             && m.GetParameters()[0].ParameterType.GetGenericTypeDefinition() == typeof(Func<>));
like image 45
SLaks Avatar answered Sep 29 '22 13:09

SLaks