开发者

Can we modify this code to return the name of a method instead of a property?

Looking fo开发者_开发百科r a clean way to discover the string name of a method in a type safe way.

Here is what I have for properties, but I'm having trouble figuring out how to do it for methods.

class Program
{
    class Customer
    {
        public String Id { get; set; }
    }

    public static String GetPropertyName<T>(
        Expression<Func<T, Object>> selector) where T : class
    {
        var expression = (MemberExpression)selector.Body;
        return expression.Member.Name;
    }

    static void Main(string[] args)
    {
        String propertyName = GetPropertyName<Customer>(c => c.Id);
    }
}


Pretty much by changing to:

    var expression = (MethodCallExpression)selector.Body;
    return expression.Method.Name;

with the notable exception that you will need an Action<T> option to handle void methods. You will have to supply dummy parameter values, of course - if you really want you can obtain those too.

Actually, your existing code might not be robust; you may need to throw away a cast operation (to box the int to an object).

public static string GetMethodName<T>(Expression<Func<T, Object>> selector) where T : class
{
    var expression = (MethodCallExpression)(selector.Body is UnaryExpression ? ((UnaryExpression)selector.Body).Operand : selector.Body);
    return expression.Method.Name;
}
public static string GetMethodName<T>(Expression<Action<T>> selector) where T : class
{
    var expression = (MethodCallExpression)(selector.Body is UnaryExpression ? ((UnaryExpression)selector.Body).Operand : selector.Body);
    return expression.Method.Name;
}


If it helps, our code base uses the following:

public class TypeHelper
{
    private static PropertyInfo GetPropertyInternal(LambdaExpression p)
    {
        MemberExpression memberExpression;

        if (p.Body is UnaryExpression)
        {
            UnaryExpression ue = (UnaryExpression)p.Body;
            memberExpression = (MemberExpression)ue.Operand;
        }
        else
        {
            memberExpression = (MemberExpression)p.Body;
        }
        return (PropertyInfo)(memberExpression).Member;
    }

    public static string GetPropertyName<TObject>(Expression<Func<TObject, object>> p)
    {
        return GetPropertyNameInternal(p);
    }

    public static string GetPropertyName<TObject, T>(Expression<Func<TObject, T>> p)
    {
        return GetPropertyNameInternal(p);
    }

    public static string GetPropertyName<T>(Expression<Func<T>> p)
    {
        return GetPropertyNameInternal(p);
    }

    public static string GetPropertyName(Expression p)
    {
        return GetPropertyNameInternal((LambdaExpression) p);
    }

    private static string GetPropertyNameInternal(LambdaExpression p)
    {
        return GetPropertyInternal(p).Name;
    }

    public static PropertyInfo GetProperty<TObject>(Expression<Func<TObject, object>> p)
    {
        return GetPropertyInternal(p);
    }

    public static PropertyInfo GetProperty<TObject, T>(Expression<Func<TObject, T>> p)
    {
        return GetPropertyInternal(p);
    }

    public static PropertyInfo GetProperty<T>(Expression<Func<T>> p)
    {
        return GetPropertyInternal(p);
    }
}

That gives you the ability to do:

var propertyName = TypeHelper.GetPropertyName<Customer>(c => c.Id);

Or

var propertyName = TypeHelper.GetPropertyName(() => this.Id); // If inside Customer class


If you happen to have System.Web.Mvc, you can use ExpressionHelper.GetExpressionText(expression), like so:

Expression<Func<Response, string>> expression = r => r.Message;
Assert.AreEqual("Message", ExpressionHelper.GetExpressionText(expression));

(Response being a custom class with a Message property.)

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜