【问题标题】:Evaluation Expression<Func<>> with variables带有变量的求值表达式<Func<>>
【发布时间】:2020-03-27 22:32:22
【问题描述】:

我们公司有一个框架,它将查询请求为 Expression(Func(T, bool)),其中 T 是 Buiniess 对象的给定类型。

我需要为此编写一个提供程序以及评估表达式内容的内容

如果我有这样的查询:

Expression<Func<Person, bool>> expr;
expr = (p) => p.Name == "Smith";

这没问题,然后我可以使用表达式的 Body 属性给出以下结果

Body = {(p.Name == "Smith")}

如果我使用这样的变量:

Expression<Func<Person, bool>> expr;
string nameToFind = "Smith";
expr = (p) => p.Name == name;

我得到以下结果:

Body = {(p.Name == value(TestConsole.Program+<>c__DisplayClass0_0).nameToFind)}

在这种情况下,我想要的是解析表达式中的变量值,就像第一个没有变量的示例一样。

这可能吗? 我会非常感谢一个例子或提示

【问题讨论】:

  • 您需要执行一些自下而上的分析以确定可以/应该评估什么,然后评估这些子表达式并在表达式树中替换它们。在这种情况下,您基本上会将显示类/闭包标识为常量,对其进行评估并替换它。 github.com/mattwar/iqtoolkit/blob/master/src/IQToolkit/… 就是一个例子。 docs.microsoft.com/en-us/archive/blogs/mattwar/… 是一个关于这个主题的好(虽然老)系列。我知道的不足以写一个答案,但我之前已经这样做了,按照链接
  • 您的Expression 课程是什么?你如何访问它的Body
  • 类来自dotnet框架 System.Linq.Expressions.Expression --- Body是Expression类的属性,Result是Expression.Body.ToString()函数的输出

标签: c# reflection expression


【解决方案1】:

您想要做的是替换任何具有ConstantExpression 类型左侧的MemberExpression,使用反射来获取值。这就是 ExpressionVisitor 的用途。

public class Simplify : ExpressionVisitor{
    protected override Expression VisitMember(MemberExpression node){
        var expr = Visit(node.Expression);
        if (expr is ConstantExpression c){
            if (node.Member is PropertyInfo prop)
                return Expression.Constant(prop.GetValue(c.Value), prop.PropertyType);
            if (node.Member is FieldInfo field)
                return Expression.Constant(field.GetValue(c.Value), field.FieldType);
        }
        return node.Update(expr);
    }
}

expr = new Simplify().Visit(expr);

【讨论】:

  • 非常感谢,这正是我的问题的确切解决方案,太好了!
猜你喜欢
  • 1970-01-01
  • 2019-02-21
  • 1970-01-01
  • 1970-01-01
  • 2023-03-20
  • 2015-10-27
  • 2015-03-02
  • 1970-01-01
  • 2015-03-29
相关资源
最近更新 更多