与えられた
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が投稿したものとほぼ同じですが、1つの追加機能があります。
あなたがタイプを持っているなら、言う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
。
説明するシナリオは他にもあります。しかし、単純な一連のプロパティ式の場合、この方法は非常にうまく機能します。
私が作成したプロジェクトを使用して、ラムダを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