Retrieving Property name from lambda expression

c# expression-trees lambda linq

Question

Is there a better way to get the Property name when passed in via a lambda expression? Here is what i currently have.

eg.

GetSortingInfo<User>(u => u.UserId);

It worked by casting it as a memberexpression only when the property was a string. because not all properties are strings i had to use object but then it would return a unaryexpression for those.

public static RouteValueDictionary GetInfo<T>(this HtmlHelper html, 
    Expression<Func<T, object>> action) where T : class
{
    var expression = GetMemberInfo(action);
    string name = expression.Member.Name;

    return GetInfo(html, name);
}

private static MemberExpression GetMemberInfo(Expression method)
{
    LambdaExpression lambda = method as LambdaExpression;
    if (lambda == null)
        throw new ArgumentNullException("method");

    MemberExpression memberExpr = null;

    if (lambda.Body.NodeType == ExpressionType.Convert)
    {
        memberExpr = 
            ((UnaryExpression)lambda.Body).Operand as MemberExpression;
    }
    else if (lambda.Body.NodeType == ExpressionType.MemberAccess)
    {
        memberExpr = lambda.Body as MemberExpression;
    }

    if (memberExpr == null)
        throw new ArgumentException("method");

    return memberExpr;
}

Accepted Answer

I found another way you can do it was to have the source and property strongly typed and explicitly infer the input for the lambda. Not sure if that is correct terminology but here is the result.

public static RouteValueDictionary GetInfo<T,P>(this HtmlHelper html, Expression<Func<T, P>> action) where T : class
{
    var expression = (MemberExpression)action.Body;
    string name = expression.Member.Name;

    return GetInfo(html, name);
}

And then call it like so.

GetInfo((User u) => u.UserId);

and voila it works.
Thanks all.


Expert Answer

Well, there's no need to call .Name.ToString(), but broadly that is about it, yes. The only consideration you might need is whether x.Foo.Bar should return "Foo", "Bar", or an exception - i.e. do you need to iterate at all.

(re comment) for more on flexible sorting, see here.




Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Is this KB legal? Yes, learn why
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Is this KB legal? Yes, learn why