29

주어진

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, 이것은 가장 깊게 중첩 된 이름 만 가져옵니다. "Prop1.SubProp1"대신 "SubProp1"

어쨌든 람다 식의 전체 속성 경로에 액세스 할 수 있습니까?


3 답변


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 : 위대한 마음은 똑같이 생각합니다! 하나의 작은 점 : 이것이 정말로 정의되어야한다고 생각하지 마십시오.GetPath<T, TProperty>(Expression<Func<T, TProperty>> expr)? 그렇지 않으면 거의 항상 그 문제에 부딪 히게됩니다.Convert/ConvertChecked시나리오 - 단순히 인수가 불필요하게 전달 되었기 때문입니다. (또는 나는 무엇인가 놓치고 있냐?) - Dan Tao
  • @ 단 : 네, 동의합니다. 사실, 편집 전에는 서명을 받았습니다.GetPath<T,U>(Expression<Func<T,U>> expr). 질문에 표시된 표현과 일치하도록 변경했습니다. 있는 그대로 그대로두고 OP가 선호하는 서명을 선택할 수 있다고 가정합니다. 메서드 본문의 코드는 그대로 유지됩니다. - LukeH
  • 어떻게 인덱스 (즉, 대괄호) 연산자 (들)을 포함하는 식으로 작동하도록 수정하는 방법? - joelmdev

6

내 대답을 한번보세요.이 질문.

루크 (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.

계정 할 다른 시나리오가있을 수 있습니다. 하지만 속성 표현식의 간단한 사슬에서는이 접근법이 잘 작동합니다.


  • 나는 나의 대답을 편집하고 있었다.Convert/ConvertChecked너를 편집 할 때. - LukeH
  • @ 루크 : 내가 뭐라 할 수 있니? 분명히 당신은 당신이하고있는 것을 알고 있습니다;) - Dan Tao

0

람다를 자바 스크립트로 변환하기 위해 만든 프로젝트를 사용할 수 있습니다.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

연결된 질문


관련된 질문

최근 질문