The other day I came across a comment in the code base of the application I'm currently working on that said the following.
// Having to loop through the GetMethods() array is pretty rubbish, even if we are using LINQ. If someone knows how to use GetMethod to get the generic method definition, then correct the code, email me and I'll buy you a pint.
Now looking into this issue it turns out that the author is correct, you cannot actually use Type.GetMethod() to invoke a Generic Method. As a result the approach the dev used was to call Type.GetMethods() which returns all methods on the type and then apply some linq filtering to identify the generic method they wish to invoke. Once filtered a quick call to MakeGenericMethod then you can invoke it. This is shown below.
typeof(FrameworkHelper)
.GetMethods()
.Where(method => method.IsGenericMethod && method.Name == "DeleteEntity")
.Select(method => method.MakeGenericMethod(actualEntityType))
.First()
.Invoke(null, new object[] { entity });
So having a think about this for a bit and then recalling some great blog posts I had read from Bart De Smet's blog about expression tree's I wondered if we could use the Expression.Call method to achieve the same results. After some tinkering with the overloads for this method I eventually figured it out and result is shown below.
ParameterExpression param = Expression.Parameter(typeof(Entity), "param");
var method = Expression.Call(typeof(FrameworkHelper), "DeleteEntity", new[] { typeof(Entity) }, param).Method;
method.Invoke(null, new object[] { entity });
In the code above we create an instance of a Parameter expression which requires the Type of the parameter we are going to pass to the method. Then in order to invoke the method we need to build the call expression on line 2. Here we use the Expression.Call static method which has a number of overloads.
The first param is the type which holds the static method we wish to invoke, the next paramter is the method name which is passed as string. The third paramter is the types that the method signature defines. This is passed as an array of objects. Finally is the ParamExpression we constructed on the previous line. The final part once we have the methodInfo is to invoke it by passing the instance of Entity.
The Expression class supports a huge array of static methods which can be used to build code dynamically and with .NET 4.0 we get a lot more support for more complex issues such as flow control, block statements etc.
Hope this quick sample sparks your interest for Expressions support in .net.
Update - Had an email from Bart about this post and he has suggested an elegant approach to this problem. Bart's approach below.
You could also have the C# compiler do all the work for you and write a simple helper method (assuming you don't need to find the method by an externally provided name at runtime...):
static MethodInfo GetMethod(Expression e)
{
return ((MethodCallExpression)e.Body).Method;
}
Now call this as follows:
GetMethod(() => new int[0].Select(x => x.ToString()))
This will return the MethodInfo for Enumerable.Select.
Hope this helps,
-Bart