zoukankan      html  css  js  c++  java
  • Linq之Expression初见

    目录

    写在前面

    系列文章

    Expression

    表达式树创建方式

    一个例子

    总结

    写在前面

    上篇文章介绍了扩展方法,这篇文章开始将陆续介绍在linq中使用最多的表达式树的相关概念,以概念及例子一一列出如何在代码中使用Expression。

    系列文章

    Linq之Lambda表达式初步认识

    Linq之Lambda进阶

    Linq之隐式类型、自动属性、初始化器、匿名类

    Linq之扩展方法

    Expression

    还是老样子,首先看MSDN中对表达式树的描述

    表达式树以树形数据结构表示代码,其中每一个节点都是一种表达式,比如方法调用和 x < y 这样的二元运算等。

    你可以对表达式树中的代码进行编辑和运算。 这样能够动态修改可执行代码、在不同数据库中执行 LINQ 查询以及创建动态查询。 

    表达式树又称为“表达式目录树”,以数据形式表示语言级代码,它是一种抽象语法树或者说是一种数据结构。

    通过上面的描述,你会发现表达式树的作用:动态修改可执行代码、在不同数据库中执行Linq查询及创建动态查询。那它是如何做到的呢?那下面就开始咱们的表达式树之旅吧。

    表达式树创建方式

    表达式树创建方式分为两种:以lambda表达式的方式创建,通过API静态方法创建。

    若 lambda 表达式被分配给 Expression<TDelegate> 类型的变量,则编译器可以发射代码以创建表示该 lambda 表达式的表达式树。

    看一个例子:

    1   static void Main(string[] args)
    2         {
    3             System.Linq.Expressions.Expression<Func<int, bool>> lambda = num => num >= 5;
    4         }

    上面的代码意思就以表达式目录树的形式将强类型的lambda表达式num=>num>=5标识为数据结构。

    通过 API 创建表达式树需要使用 Expression 类。

    该类包含创建特定类型表达式树节点的静态工厂方法,比如表示参数变量的 ParameterExpression,或者是表示方法调用的 MethodCallExpression。 System.Linq.Expressions 名称空间还解释了 ParameterExpression、MethodCallExpression和另一种具体表达式类型。 这些类型来源于抽象类型 Expression。

    那么我使用API的方式创建上面例子中的表达式树:

    说的很高大上,其实就是类Expression的一系列静态方法。

    首先引入命名空间

    using System.Linq.Expressions;
     1         static void Main(string[] args)
     2         {
     3             //创建lambda表达式 num=>num>=5
     4             //第一步创建输入参数,参数名为num,类型为int类型
     5             ParameterExpression numParameter = Expression.Parameter(typeof(int), "num");
     6             //第二步创建常量表达式5,类型int
     7             ConstantExpression constant = Expression.Constant(5, typeof(int));
     8             //第三步创建比较运算符>=,大于等于,并将输入参数表达式和常量表达式输入
     9             //表示包含二元运算符的表达式。BinaryExpression继承自Expression
    10             BinaryExpression greaterThanOrEqual = Expression.GreaterThanOrEqual(numParameter, constant);
    11             //第四步构建lambda表达式树
    12             //Expression.Lambda<Func<int, bool>>:通过先构造一个委托类型来创建一个 LambdaExpression
    13             Expression<Func<int, bool>> lambda = Expression.Lambda<Func<int, bool>>(greaterThanOrEqual, numParameter);
    14         }

     

    通过上面的代码你会发现这种方式在创建的时候,lambda表达式的左右及二元运算符都要分别的创建,然后在通过Expression.Lambda方法构建lambda表达式。

    一个例子

    在 .NET Framework 4 中,API 表达式树还支持赋值表达式和控制流表达式,比如循环、条件块和 try-catch 块等。

    看一个例子,通过API表达式树创建一个利用循环求1到n的和的表达式树。

    如果能这样写该有多好啊

    1             Expression<Func<int, int>> lambda = n =>
    2             {
    3                 int result = 0;
    4                 for (int j = n; j >= 0; j--)
    5                 {
    6                     result += j;
    7                 }
    8                 return result;
    9             };

    可惜

    通过API创建表达式树,可以创建更为复杂的表达式树,这里先尝尝鲜

     1     class Program
     2     {
     3         static void Main(string[] args)
     4         {
     5             //变量表达式
     6             ParameterExpression i = Expression.Variable(typeof(int), "i");
     7             //变量表达式
     8             ParameterExpression sum = Expression.Variable(typeof(int), "sum");
     9             //跳出循环标志
    10             LabelTarget label = Expression.Label(typeof(int));
    11             //块表达式
    12             BlockExpression block =
    13                 Expression.Block(
    14                 //添加局部变量
    15                     new[] { sum },
    16                 //为sum赋初值 sum=1
    17                 //Assign表示赋值运算符
    18                     Expression.Assign(sum, Expression.Constant(1, typeof(int))),
    19                 //loop循环
    20                     Expression.Loop(
    21                 //如果为true 然后求和,否则跳出循环
    22                         Expression.IfThenElse(
    23                 //如果i>=0
    24                         Expression.GreaterThanOrEqual(i, Expression.Constant(0, typeof(int))),
    25                 //sum=sum+i;i++;
    26                                   Expression.AddAssign(sum, Expression.PostDecrementAssign(i)),
    27                 //跳出循环
    28                             Expression.Break(label, sum)
    29                         ), label
    30                      )  // Loop ends
    31                  );
    32             int resutl = Expression.Lambda<Func<int, int>>(block, i).Compile()(100);
    33             Console.WriteLine(resutl);
    34             Console.Read();
    35         }
    36     }

    输出结果

    总结

    本篇文章主要介绍了表达式树的概念及两种创建方式。在文章的结尾给出了一个例子,也是先尝尝鲜,对于代码中的一些静态方法可先参考注释。下篇文章将介绍一些Expression的常用的静态方法。

    参考文章

    http://msdn.microsoft.com/zh-cn/library/bb397951.aspx

  • 相关阅读:
    linux下一个网卡配置多个ip(转)
    实验室生活:第一个月
    关闭或开启Linux上的iptables防火墙,SSH端口(转)
    TcpTrace追踪远程服务器的soap信息
    我的mysql学习笔记(1)mysql的安装
    大型网站架构演变和知识体系[转载]
    ms sql一些有用的语句
    我的mysql学习笔记(2)mysql基本的命令
    SQL Server 2008 R2数据库镜像部署[转]
    C++ 自定义动态数组模板
  • 原文地址:https://www.cnblogs.com/wolf-sun/p/4222473.html
Copyright © 2011-2022 走看看