Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/334.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 给定ExpressionType.MemberAccess类型,如何获取字段值?_C#_Reflection_Expression Trees - Fatal编程技术网

C# 给定ExpressionType.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

我正在解析表达式树。给定ExpressionType.MemberAccess的节点类型,如何获取该字段的值

从C#MSDN文档: MemberAccess是表示读取字段或属性的节点

一段代码片段会非常非常有用。提前感谢

我的代码如下所示:

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”的表达式
i、 e.如果您可以将
.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();