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

时间:2010-06-15 23:35:16

标签: c# .net linq

给出

Expression<Func<T, object>> 

(例如x =&gt; x.Prop1.SubProp),我想根据需要创建一个字符串“Prop1.SubProp”。

如果是单次访问(例如x =&gt; x.Prop1),我可以轻松地执行此操作:

MemberExpression body = (expression.Body.NodeType == ExpressionType.Convert) ? (MemberExpression)((UnaryExpression)expression.Body).Operand : (MemberExpression)expression.Body;
return body.Member.Name;

但是,如果有更深的嵌套,例如x =&gt; x.Prop1.SubProp1,这只获得嵌套最深的名称,例如: “SubProp1”而不是“Prop1.SubProp1”

是否有访问lambda表达式的完整属性路径?

3 个答案:

答案 0 :(得分: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());
}

答案 1 :(得分:6)

看看我对this question的回答。

与LukeH发布的内容非常相似,还有一个附加功能:

如果您有类型MyClass,类型为MyProperty的属性int,则可以写下:

Expression<Func<MyClass, object>> e = x => x.MyProperty;

此处表达式e.Body 一个MemberExpression,因此简单的while (me != null) me = me.Expression as MemberExpression将无效。

解决方案是另外检查UnaryExpressionNodeType == Convert还是ConvertChecked

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

答案 2 :(得分:0)

您可以使用我创建的项目将lambda转换为javascript:lambda2js

仅使用属性和索引器时,结果应该是您所需要的。

示例1:单个属性路径

Expression<Func<MyClass, object>> expr = x => x.Phone;
var js = expr.CompileToJavascript();
// returns: Phone

示例2:包含字符串字典索引器的路径

Expression<Func<MyClass, object>> expr = x => x.PhonesByName["Miguel"];
var js = expr.CompileToJavascript();
// returns: PhonesByName["Miguel"]

示例3:包含索引器和多个级别的复杂路径

Expression<Func<MyClass, object>> expr = x => x.SomeProp["Miguel"].Subprop[0].A.B;
var js = expr.CompileToJavascript();
// returns: SomeProp["Miguel"].Subprop[0].A.B