Getting hold of the MethodInfo of a generic method via Reflection (so you can invoke it dynamically, for example) can be a bit of a pain. So this afternoon I formulated a pain-killer, SymbolExtensions.GetMethodInfo. It’s not fussy: it works for non-generic methods too. You use it like this:
internal class SymbolExtensionsTests { [Test] public void GetMethodInfo_should_return_method_info() { var methodInfo = SymbolExtensions.GetMethodInfo<TestClass>(c => c.AMethod()); methodInfo.Name.ShouldEqual("AMethod"); } [Test] public void GetMethodInfo_should_return_method_info_for_generic_method() { var methodInfo = SymbolExtensions.GetMethodInfo<TestClass>(c => c.AGenericMethod(default(int))); methodInfo.Name.ShouldEqual("AGenericMethod"); methodInfo.GetParameters().First().ParameterType.ShouldEqual(typeof(int)); } [Test] public void GetMethodInfo_should_return_method_info_for_static_method_on_static_class() { var methodInfo = SymbolExtensions.GetMethodInfo(() => StaticTestClass.StaticTestMethod()); methodInfo.Name.ShouldEqual("StaticTestMethod"); methodInfo.IsStatic.ShouldBeTrue(); } }
The active ingredient, as you can see, is Lambda expressions:
using System.Linq; using System.Linq.Expressions; using System.Reflection; using System; public static class SymbolExtensions { /// <summary> /// Given a lambda expression that calls a method, returns the method info. /// </summary> /// <typeparam name="T"></typeparam> /// <param name="expression">The expression.</param> /// <returns></returns> public static MethodInfo GetMethodInfo(Expression<Action> expression) { return GetMethodInfo((LambdaExpression)expression); } /// <summary> /// Given a lambda expression that calls a method, returns the method info. /// </summary> /// <typeparam name="T"></typeparam> /// <param name="expression">The expression.</param> /// <returns></returns> public static MethodInfo GetMethodInfo<T>(Expression<Action<T>> expression) { return GetMethodInfo((LambdaExpression)expression); } /// <summary> /// Given a lambda expression that calls a method, returns the method info. /// </summary> /// <typeparam name="T"></typeparam> /// <param name="expression">The expression.</param> /// <returns></returns> public static MethodInfo GetMethodInfo<T, TResult>(Expression<Func<T, TResult>> expression) { return GetMethodInfo((LambdaExpression)expression); } /// <summary> /// Given a lambda expression that calls a method, returns the method info. /// </summary> /// <param name="expression">The expression.</param> /// <returns></returns> public static MethodInfo GetMethodInfo(LambdaExpression expression) { MethodCallExpression outermostExpression = expression.Body as MethodCallExpression; if (outermostExpression == null) { throw new ArgumentException("Invalid Expression. Expression should consist of a Method call only."); } return outermostExpression.Method; } }