从lambda表达式中检索属性名称

通过lambda表达式传入时是否有更好的方法来获取属性名称? 这是我目前拥有的。

例如。

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

只有当属性是一个字符串时,它才会将它作为一个元素表达式进行处理。 因为不是所有的属性都是字符串,我不得不使用对象,但它会返回一个一元表达式。

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;
}

我最近做了一个非常类似的事情来创建一个类型安全的OnPropertyChanged方法。

这是一个将返回表达式的PropertyInfo对象的方法。 如果表达式不是属性,则会引发异常。

public PropertyInfo GetPropertyInfo<TSource, TProperty>(
    TSource source,
    Expression<Func<TSource, TProperty>> propertyLambda)
{
    Type type = typeof(TSource);

    MemberExpression member = propertyLambda.Body as MemberExpression;
    if (member == null)
        throw new ArgumentException(string.Format(
            "Expression '{0}' refers to a method, not a property.",
            propertyLambda.ToString()));

    PropertyInfo propInfo = member.Member as PropertyInfo;
    if (propInfo == null)
        throw new ArgumentException(string.Format(
            "Expression '{0}' refers to a field, not a property.",
            propertyLambda.ToString()));

    if (type != propInfo.ReflectedType &&
        !type.IsSubclassOf(propInfo.ReflectedType))
        throw new ArgumentException(string.Format(
            "Expression '{0}' refers to a property that is not from type {1}.",
            propertyLambda.ToString(),
            type));

    return propInfo;
}

source参数被使用,所以编译器可以对方法调用进行类型推断。 您可以执行以下操作

var propertyInfo = GetPropertyInfo(someUserObject, u => u.UserID);

我发现另一种可以做到的方式是强制类型化源和属性,并显式推断lambda的输入。 不知道这是否是正确的术语,但这是结果。

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);
}

然后像这样称呼它。

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

并说它有效。
谢谢大家。


我正在玩同样的东西,并努力工作。 它没有完全测试,但似乎处理值类型的问题(你遇到的一元表达问题)

public static string GetName(Expression<Func<object>> exp)
{
    MemberExpression body = exp.Body as MemberExpression;

    if (body == null) {
       UnaryExpression ubody = (UnaryExpression)exp.Body;
       body = ubody.Operand as MemberExpression;
    }

    return body.Member.Name;
}
链接地址: http://www.djcxy.com/p/31589.html

上一篇: Retrieving Property name from lambda expression

下一篇: QuickSort vs MergeSort on arrays of primitives in Java