给定一个Member Access lambda表达式,将其转换为具有完全访问路径的特定字符串表示

Nat*_*han 29 .net c# linq

鉴于

Expression<Func<T, object>> 
Run Code Online (Sandbox Code Playgroud)

(例如x => x.Prop1.SubProp),我想根据需要创建一个字符串"Prop1.SubProp".

在单次访问的情况下(例如x => x.Prop1),我可以轻松地执行以下操作:

MemberExpression body = (expression.Body.NodeType == ExpressionType.Convert) ? (MemberExpression)((UnaryExpression)expression.Body).Operand : (MemberExpression)expression.Body;
return body.Member.Name;
Run Code Online (Sandbox Code Playgroud)

但是,如果存在更深的嵌套,例如x => x.Prop1.SubProp1,则只获得嵌套最深的名称,例如"SubProp1"而不是"Prop1.SubProp1"

反正有没有访问lambda表达式的完整属性路径?

Luk*_*keH 34

public string GetPath<T>(Expression<Func<T, object>> expr)
{
    var stack = new Stack<string>();

    MemberExpression me;
    switch (expr.Body.NodeType)
    {
        case ExpressionType.Convert:
        case ExpressionType.ConvertChecked:
            var ue = expr.Body as UnaryExpression;
            me = ((ue != null) ? ue.Operand : null) as MemberExpression;
            break;
        default:
            me = expr.Body as MemberExpression;
            break;
    }

    while (me != null)
    {
        stack.Push(me.Member.Name);
        me = me.Expression as MemberExpression;
    }

    return string.Join(".", stack.ToArray());
}
Run Code Online (Sandbox Code Playgroud)


Dan*_*Tao 6

看看我对这个问题的回答.

与LukeH发布的内容几乎相同,还有一个附加功能:

如果你有一个类型,比如说MyClass,有物业MyProperty类型的int,你可以这样写:

Expression<Func<MyClass, object>> e = x => x.MyProperty;
Run Code Online (Sandbox Code Playgroud)

这里表达的e.Body不是一个MemberExpression这么简单的while (me != null) me = me.Expression as MemberExpression将无法工作.

解决方案是另外检查它是否UnaryExpressionNodeType == ConvertConvertChecked.

可能还有其他方案需要考虑; 但对于简单的属性表达式链,这种方法非常有效.