Phil Cooper
Phil Cooper

Reputation: 3123

Can I find a method with generic parameters using strongly typed reflection?

Here's my attempt at calling an existing generic method with a type argument. 'Strongly typed reflection' may not be a suitable term, but it basically means finding and invoking the reflected method without using a name string.

public class TestClass
{
    public static void Test(Type type)
    {
        InvokeTestMethodWithType(type);
    }

    private void Test<T>() { ... }

    private static void InvokeTestMethodWithType(Type type)
    {
        // This doesn't compile! - can I find Test<> using this approach?
        Expression<Func<TestClass, Action>> ex = x => x.Test<>;

        // invoke it
        ((MethodCallExpression)ex.Body).Method.MakeGenericMethod(type).Invoke(new TestClass(), null);
    }
}

Sample call would end up call the private Test().

TestClass.Test(typeof(Foo))

As you can see, I'm struggling with the expression and not entirely sure if it can be executed in this manner.

Do I have to dummy invoke the action in the expression like this post?

x => x.Test<object>()

Upvotes: 1

Views: 364

Answers (1)

Luaan
Luaan

Reputation: 63732

The trick I use is simple: pass a fake generic type argument:

Expression<Func<TestClass, WhateverTestReturns>> ex = x => x.Test<string>();

// invoke it
((MethodCallExpression)ex.Body)
  .Method
  .GetGenericMethodDefinition()
  .MakeGenericMethod(type)
  .Invoke(new TestClass(), null);

The method call expression will then contain a method info for Test<string>(), but you can easily use GetGenericMethodDefinition to remove the generic argument, and then MakeGenericMethod to put a different one back in its place.

You don't even need to use Expression in a case like this - simply cast TestClass.Test<string> to a delegate, and you'll have a Method property that gives you the same method info.

Upvotes: 2

Related Questions