Reputation: 3123
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
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