您好, 欢迎来到 !    登录 | 注册 | | 设为首页 | 收藏本站

从表达式中以字符串形式获取属性>

从表达式中以字符串形式获取属性>

诀窍是:这种形式的任何表达方式…

obj => obj.A.B.C // etc.

…实际上只是一堆嵌套MemberExpression对象。

首先,您必须:

MemberExpression: obj.A.B.C
Expression:       obj.A.B   // MemberExpression
Member:           C

评估Expression上面 _的MemberExpression_为您提供:

MemberExpression: obj.A.B
Expression:       obj.A     // MemberExpression
Member:           B

最后,以上 (在“顶部”),你必须:

MemberExpression: obj.A
Expression:       obj       // note: not a MemberExpression
Member:           A

因此,似乎很明显,解决此问题的方法是通过检查up 的Expression属性MemberExpression直到不再成为a本身为止MemberExpression

:看来您的问题有一个额外的旋转。可能您有一些lambda 看起来Func<T, int>

p => p.Age

…但 实际上是 一个Func<T, object>; 在这种情况下,编译器会将上面的表达式转换为:

p => Convert(p.Age)

实际上,针对此问题进行调整并不像看起来那样困难。查看我的更新代码,了解一种处理它的方法。请注意,通过抽象化用于MemberExpression脱离其自身方法TryFindMemberExpression)的代码,该方法可以使GetFullPropertyName方法保持相当干净,并允许您将来添加其他检查- 如果也许您发现自己面对的是 环境,最初并没有考虑-无需花费太多代码

举例说明:这段代码我有用。

// code adjusted to prevent horizontal overflow
static string GetFullPropertyName<T, TProperty>
(Expression<Func<T, TProperty>> exp)
{
    MemberExpression memberExp;
    if (!TryFindMemberExpression(exp.Body, out memberExp))
        return string.Empty;

    var memberNames = new Stack<string>();
    do
    {
        memberNames.Push(memberExp.Member.Name);
    }
    while (TryFindMemberExpression(memberExp.Expression, out memberExp));

    return string.Join(".", memberNames.ToArray());
}

// code adjusted to prevent horizontal overflow
private static bool TryFindMemberExpression
(Expression exp, out MemberExpression memberExp)
{
    memberExp = exp as MemberExpression;
    if (memberExp != null)
    {
        // heyo! that was easy enough
        return true;
    }

    // if the compiler created an automatic conversion,
    // it'll look something like...
    // obj => Convert(obj.Property) [e.g., int -> object]
    // OR:
    // obj => ConvertChecked(obj.Property) [e.g., int -> long]
    // ...which are the cases checked in IsConversion
    if (IsConversion(exp) && exp is UnaryExpression)
    {
        memberExp = ((UnaryExpression)exp).Operand as MemberExpression;
        if (memberExp != null)
        {
            return true;
        }
    }

    return false;
}

private static bool IsConversion(Expression exp)
{
    return (
        exp.NodeType == ExpressionType.Convert ||
        exp.NodeType == ExpressionType.ConvertChecked
    );
}

用法

Expression<Func<Person, string>> simpleExp = p => p.FirstName;
Expression<Func<Person, string>> complexExp = p => p.Address.State.Abbreviation;
Expression<Func<Person, object>> ageExp = p => p.Age;

Console.WriteLine(GetFullPropertyName(simpleExp));
Console.WriteLine(GetFullPropertyName(complexExp));
Console.WriteLine(GetFullPropertyName(ageExp));

输出

FirstName
Address.State.Abbreviation
Age
其他 2022/1/1 18:14:48 有522人围观

撰写回答


你尚未登录,登录后可以

和开发者交流问题的细节

关注并接收问题和回答的更新提醒

参与内容的编辑和改进,让解决方法与时俱进

请先登录

推荐问题


联系我
置顶