Подтвердить что ты не робот

Учитывая выражение лямбда-члена Member Access, преобразуйте его в определенное строковое представление с полным доступом

Учитывая

Expression<Func<T, object>> 

(например, 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;

Однако, если есть более глубокое вложение, например. x = > x.Prop1.SubProp1, это получает только самое глубоко вложенное имя, например. "SubProp1" вместо "Prop1.SubProp1"

Есть ли вообще доступ к полному пути свойств выражения лямбда?

4b9b3361

Ответ 1

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

Ответ 2

Взгляните на мой ответ на этот вопрос.

В значительной степени то же, что и LukeH, с одной дополнительной функцией:

Если у вас есть тип, скажем, MyClass, с свойством MyProperty типа int, вы можете написать это:

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

Здесь выражение e.Body не является MemberExpression, поэтому простой while (me != null) me = me.Expression as MemberExpression не будет работать.

Решение должно дополнительно проверить, если оно UnaryExpression с NodeType == Convert или ConvertChecked.

Могут быть другие сценарии для учета; но для простых цепочек выражений свойств этот подход работает очень хорошо.

Ответ 3

Вы можете использовать проект, который я создал для преобразования 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