Lambda表达式树解析
我试图在项目中使用Lambda表达式映射到第三方查询API。 所以,我正在手工解析Expression树。
如果我传入一个lambda表达式,如:
p => p.Title == "title"
一切正常。
但是,如果我的lambda表达式如下:
p => p.Title == myaspdropdown.SelectedValue
使用.NET调试器,我没有看到该函数的实际值。 相反,我看到类似的东西:
p => p.Title = (value(ASP.usercontrols_myaspusercontrol_ascx).myaspdropdown.SelectedValue)
是什么赋予了? 当我尝试将表达式的右侧作为字符串抓取时,我得到(value(ASP.usercontrols_myaspusercontrol_ascx).myaspdropdown.SelectedValue)
而不是实际值。 我如何获得实际价值?
请记住,当您将lambda表达式作为表达式树处理时,您没有可执行代码。 相反,你有一个表达元素树,它构成你写的表达式。
Charlie Calvert有一篇很好的post ,详细讨论了这一点。 包含使用表达式可视化器来调试表达式的示例。
在您的情况下,要获取相等表达式右侧的值,您需要创建一个新的lambda表达式,编译它然后调用它。
我已经把一个快速的例子写在了一起 – 希望它能满足你的需求。
public class Class1 { public string Selection { get; set; } public void Sample() { Selection = "Example"; Example(p => p.Title == Selection); } public void Example(Expression> exp) { BinaryExpression equality = (BinaryExpression)exp.Body; Debug.Assert(equality.NodeType == ExpressionType.Equal); // Note that you need to know the type of the rhs of the equality var accessorExpression = Expression.Lambda>(equality.Right); Func accessor = accessorExpression.Compile(); var value = accessor(); Debug.Assert(value == Selection); } } public class Book { public string Title { get; set; } }
要获得实际值,您需要将表达式树的逻辑应用于您已获得的任何上下文。
表达式树的整个要点是它们将逻辑表示为数据而不是评估表达式。 你需要弄清楚lambda表达式的真正含义。 这可能意味着根据本地数据评估它的某些部分 – 您需要自己决定。 表达式树非常强大,但解析和使用它们并不是一件简单的事情。 (问问任何写过LINQ提供者的人…… Frans Bouma多次哀叹这些困难。)
刚刚在同一个问题上苦苦挣扎,感谢Bevan。 在扩展上,以下是可用于提取值的通用模式(在我的查询引擎中使用此模式)。
[TestFixture] public class TestClass { [Test] public void TEst() { var user = new User {Id = 123}; var idToSearch = user.Id; var query = Creator.CreateQuery() .Where(x => x.Id == idToSearch); } } public class Query { public Query Where(Expression> filter) { var rightValue = GenericHelper.GetVariableValue(((BinaryExpression)((UnaryExpression)filter.Body).Operand).Right.Type, ((BinaryExpression)((UnaryExpression)filter.Body).Operand).Right); Console.WriteLine(rightValue); return this; } } internal class GenericHelper { internal static object GetVariableValue(Type variableType, Expression expression) { var targetMethodInfo = typeof(InvokeGeneric).GetMethod("GetVariableValue"); var genericTargetCall = targetMethodInfo.MakeGenericMethod(variableType); return genericTargetCall.Invoke(new InvokeGeneric(), new[] { expression }); } } internal class InvokeGeneric { public T GetVariableValue (Expression expression) where T : class { var accessorExpression = Expression.Lambda>(expression); var accessor = accessorExpression.Compile(); return accessor(); } }
我不确定我理解。 你在哪里“看到”那个? 那是在设计时还是在运行时? Lambda表达式基本上可以被认为是匿名委托,并且将与延迟执行一起运行。 所以你不应该期望在执行过去之前看到分配的值,显然。
我不认为这真的是你的意思…如果你澄清一下这个问题,我可以帮助:)
上述就是C#学习教程:Lambda表达式树解析分享的全部内容,如果对大家有所用处且需要了解更多关于C#学习教程,希望大家多多关注—计算机技术网(www.ctvol.com)!
本文来自网络收集,不代表计算机技术网立场,如涉及侵权请联系管理员删除。
ctvol管理联系方式QQ:251552304
本文章地址:https://www.ctvol.com/cdevelopment/1301103.html