C# 给定ExpressionType.MemberAccess类型,如何获取字段值?
我正在解析表达式树。给定ExpressionType.MemberAccess的节点类型,如何获取该字段的值 从C#MSDN文档: MemberAccess是表示读取字段或属性的节点 一段代码片段会非常非常有用。提前感谢 我的代码如下所示:C# 给定ExpressionType.MemberAccess类型,如何获取字段值?,c#,reflection,expression-trees,C#,Reflection,Expression Trees,我正在解析表达式树。给定ExpressionType.MemberAccess的节点类型,如何获取该字段的值 从C#MSDN文档: MemberAccess是表示读取字段或属性的节点 一段代码片段会非常非常有用。提前感谢 我的代码如下所示: public static List<T> Filter(Expression<Func<T, bool>> filterExp) { //the expression is indeed a binary expres
public static List<T> Filter(Expression<Func<T, bool>> filterExp)
{
//the expression is indeed a binary expression in this case
BinaryExpression expBody = filterExp.Body as BinaryExpression;
if (expBody.Left.NodeType == ExpressionType.MemberAccess)
//do something with ((MemberExpressionexpBody.Left).Name
//right hand side is indeed member access. in fact, the value comes from //aspdroplist.selectedvalue
if (expBody.Right.NodeType == ExpressionType.MemberAccess)
{
//how do i get the value of aspdroplist.selected value?? note: it's non-static
}
//return a list
}
公共静态列表过滤器(表达式过滤器exp)
{
//在这种情况下,表达式实际上是一个二进制表达式
BinaryExpression expBody=filterExp.Body作为BinaryExpression;
if(expBody.Left.NodeType==ExpressionType.MemberAccess)
//使用((MemberExpressionexpBody.Left).Name执行某些操作
//右侧实际上是成员访问。事实上,该值来自//aspdroplist.selectedvalue
if(expBody.Right.NodeType==ExpressionType.MemberAccess)
{
//如何获取aspdroplist.selected值??注意:它是非静态的
}
//返回列表
}
[为清晰起见更新]
首先,将表达式
强制转换为成员表达式
MemberExpression
有两件有趣的事情:
- .Member-将
/属性yinfo
发送给成员字段信息
- .Expression-要计算以获取.Member的“obj”的表达式
.Expression
计算为“obj”,并且.Member
是字段信息
,那么您可以通过字段信息
上的.GetValue(obj)
获得实际值(并且属性信息
非常类似)
问题是计算.Expression
非常棘手;-p
显然,如果结果是一个常量表达式
,您会很幸运,但在大多数情况下,它不是;它可能是一个参数表达式
(在这种情况下,您需要知道要计算的实际参数值),或者是表达式
的任何其他组合
在许多情况下,一个简单的(可能是惰性的)选项是使用.Compile()
让.NET framework完成繁重的工作;然后可以将lambda作为类型化委托进行计算(传递lambda需要的任何参数)。然而,这并不总是一个选项
显示这是多么复杂;考虑这个琐碎的例子(我在每一步都硬编码,而不是测试等):
使用系统;
使用System.Linq.Expressions;
运用系统反思;
福班
{
公共字符串条{get;set;}
}
静态类程序
{
静态void Main()
{
Foo Foo=新Foo{Bar=“abc”};
表达式func=()=>foo.Bar;
MemberExpression outerMember=(MemberExpression)func.Body;
PropertyInfo outerProp=(PropertyInfo)outerMember.Member;
MemberExpression innerMember=(MemberExpression)outerMember.Expression;
FieldInfo innerField=(FieldInfo)innerMember.Member;
ConstantExpression ce=(ConstantExpression)innerMember.Expression;
对象innerObj=ce.Value;
对象outerObj=innerField.GetValue(innerObj);
字符串值=(字符串)outerProp.GetValue(outerbj,null);
}
}
非常感谢上面的马克·格雷维尔。我真的很感谢他的帮助
事实证明,就我而言,问题可以通过以下方式解决:
object value = Expression.Lambda(expBody.Right).Compile().DynamicInvoke();
再次感谢Mark!非常感谢Marc.Expression属性的值是…更有趣的:{value(ASP.usercontrols\u mycontro\u ascx).controlname}我在泛型和反射方面做了很多工作,因此通过propertyinfo/fieldinfo检索值不起作用,因为我不确定从何处提取引用对象…我可以从memberexpression或methodinfo提取引用对象吗?这会起作用…但问题是您需要将.Expression作为值进行计算,以作为“obj”输入对于FieldInfo/PropertyInfo。您是否可以不使用.Compile()并将lambda作为委托执行?比解析简单得多…请注意,如果lambda已参数化,但您没有特定的参数-那么您将遇到困难…但是像ConstantPression这样的事情应该会自行解决好的。非常感谢Marc!!!真的…在这里以及其他地方。最终的问题是左手side是一个二进制表达式…右边不是常量表达式。我将用一些代码或更好的
object value=Expression.Lambda(Expression.Convert(expBody.right,typeof(object))).Compile().Invoke()
更新我的问题:速度非常慢。
object value = Expression.Lambda(expBody.Right).Compile().DynamicInvoke();