给出
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表达式的完整属性路径?
答案 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
将无效。
解决方案是另外检查UnaryExpression
是NodeType == 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