주어진
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"
어쨌든 람다 식의 전체 속성 경로에 액세스 할 수 있습니까?
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());
}
GetPath<T, TProperty>(Expression<Func<T, TProperty>> expr)
? 그렇지 않으면 거의 항상 그 문제에 부딪 히게됩니다.Convert
/ConvertChecked
시나리오 - 단순히 인수가 불필요하게 전달 되었기 때문입니다. (또는 나는 무엇인가 놓치고 있냐?) - Dan TaoGetPath<T,U>(Expression<Func<T,U>> expr)
. 질문에 표시된 표현과 일치하도록 변경했습니다. 있는 그대로 그대로두고 OP가 선호하는 서명을 선택할 수 있다고 가정합니다. 메서드 본문의 코드는 그대로 유지됩니다. - LukeH
내 대답을 한번보세요.이 질문.
루크 (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
.
계정 할 다른 시나리오가있을 수 있습니다. 하지만 속성 표현식의 간단한 사슬에서는이 접근법이 잘 작동합니다.
람다를 자바 스크립트로 변환하기 위해 만든 프로젝트를 사용할 수 있습니다.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