using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Text;
 
namespace MyNamespace
{
    public static class MethodSupport<T>
    {
        public static string ActionName(Expression<Func<T, Action>> expression)
        {
            return MethodName(expression);
        }
 
        public static string ActionName<TParam>(Expression<Func<T, Action<TParam>>> expression)
        {
            return MethodName(expression);
        }
 
        public static string FuncName<TResult>(Expression<Func<T, Func<TResult>>> expression)
        {
            return MethodName(expression);
        }
 
        public static string FuncName<TParam, TResult>(Expression<Func<T, Func<TParam, TResult>>> expression)
        {
            return MethodName(expression);
        }
 
        private static bool IsNET45 = Type.GetType("System.Reflection.ReflectionContext", false) != null;
 
        public static string MethodName(LambdaExpression expression)
        {
            var unaryExpression = (UnaryExpression)expression.Body;
            var methodCallExpression = (MethodCallExpression)unaryExpression.Operand;
 
            if (IsNET45)
            {
                var methodCallObject = (ConstantExpression)methodCallExpression.Object;
                var methodInfo = (MethodInfo)methodCallObject.Value;
                return methodInfo.Name;
            }
            else
            {
                var methodInfoExpression = (ConstantExpression)methodCallExpression.Arguments.Last();
                var methodInfo = (MemberInfo)methodInfoExpression.Value;
                return methodInfo.Name;
            }
 
        }
    }
 
    public class MyClass
    {
        public void Foo() { }
 
        public void Fooz(int e) { }
 
        public int Bar() { return 1; }
 
        public int Barz(int c) { return 1; }
    }
 
    public class Program
    {
 
        public static void AssertAreEqual(string first, string second)
        {
            if (first != second)
                Console.WriteLine("{0} != {1}", first, second);
            else
                Console.WriteLine("{0} == {1}", first, second);
        }
 
        public static void Main(string[] args)
        {
            AssertAreEqual("Foo", MethodSupport<MyClass>.ActionName(c => c.Foo));
 
            AssertAreEqual("Fooz", MethodSupport<MyClass>.ActionName<int>(c => c.Fooz));
 
            AssertAreEqual("Bar", MethodSupport<MyClass>.FuncName<int>(c => c.Bar));
 
            AssertAreEqual("Barz", MethodSupport<MyClass>.FuncName<int, int>(c => c.Barz));
        }
    }
}