代码之家  ›  专栏  ›  技术社区  ›  Janus007

使用BinaryExpression和分析表达式树

  •  2
  • Janus007  · 技术社区  · 15 年前

    我只是在学习表达树的早期阶段。

    据我所知,它们的好处在于,当它们被用作参数时,它们可以被解析,例如:

    Foo.Bar(x => x.Process == "On" && x.Name == "Goofy")
    

    但是,当表达式存在和内部存在时,如何解析它呢?

    也许我误解了这一切,但我看不出使用表达式的原因?我现在已经浏览了近百个网站,这些网站都试图解释表达式树是什么,它们都成功了,期望它们从来没有解释过它的用途——除了一些简单的解释“表达式树没有被编译……”

    2 回复  |  直到 12 年前
        1
  •  0
  •   Matt Ellen Bipin Vayalu    15 年前

    我使用表达式构建了一种简单的特定于域的语言。这在我工作的实际应用程序中使用,因此它不是一个玩具项目。

    我基本上创建了一个流畅的界面,允许我构建 Predicate<T> 代表,比如:

    Predicate<MyClass> condition = (new ConditionBuilder()).GreaterThanConst(9)
                                                           .And()
                                                           .LessThanConst(4)
                                                           .ToPredicate();
    

    每个方法都将相关表达式添加到当前树中。比 ToPredicate 将表达式编译为委托。

    这个 GreaterThanConst 方法如下:

    public ConditionBuilder GreaterThan(object constant)
    {
        condition = Expression.GreaterThan(Expression.Parameter(constant.GetType()), Expression.Constant(constant));
        return this;
    }
    

    在哪里? condition 是持有正在建造(生长)的树的成员吗?.

    要解析表达式,需要编写如下内容:

    Expression<Func<YourClass, bool>> expr = x => x.Process == "On" && x.Name == "Goofy";
    

    然后,您可以查看生成的表达式树,并查看其中的内容。

        2
  •  1
  •   Thomas Levesque    15 年前

    表达式以树的形式表示代码。树的每个节点表示代码的一部分。例如,问题中lambda表达式体的树如下所示:

    BinaryExpression (AndAlso)
      .Left = BinaryExpression (Equal)
        .Left = MemberExpression (x.Process)
          .Expression = ParameterExpression (x)
          .Member = MemberInfo (Process)
        .Right = ConstantExpression ("On")
      .Right = BinaryExpression (Equal)
        .Left = MemberExpression (x.Name)
          .Expression = ParameterExpression (x)
          .Member = MemberInfo (Name)
        .Right = ConstantExpression ("Goofy")
    

    通常,表达式所表示的代码不会被执行,甚至不会被编译:分析它是为了从中提取一些信息,将其转换为另一个表达式,甚至生成完全不同的内容(如Linq to SQL或Entity Framework中的SQL查询)。编译后的代码不可能做到这一点,因为无法对其进行分析(至少不容易)。