Expression 表达式目录树一

这里有两段代码:

看一下 Where 的参数

Linq To object 的 where 方法需要的参数是 委托

Linq To Sql的 where 方法需要的参数  是被 Expression 包裹的 委托

到这里 Lamada 表达式, 不一定是 匿名函数了,还有可能是数据结构

而且在 Lamada 表达式 作为 数据结构时 和作为匿名函数时是有区别的:

作为 数据结构的Lamada 表达式与普通表达式的区别   : 只有一行,不能有大括号 和 return

表达式目录树是可以转为委托的,  可以使用 Compile 方法    如下代码:  

            // 这里的Lamada 表达式是一个数据结构
            // Lamada就像声明了多个变量以及变量之间的操作关系,需要的时候还可以解开
            Expression<Func<int, int, int>> exp = (x, y) => x * y + 2;  //正常

            //作为 数据结构的Lamada 表达式与普通表达式的区别   : 只有一行,不能有大括号 和 return
            Expression<Func<int, int, int>> exp1 = (x, y) => { return x * y + 2; }; //报错

            //表达式目录树 转委托:
            exp.Compile().Invoke(78, 78);

 

其实 用   Lamada 表达式   声明 表达式目录树  是一种快捷方式 ,常规的声明如下:

最简版:2+5

  // 快捷
            Expression<Func<int>> exp2 = () => 2 + 544;

            // 常规
            ConstantExpression right = Expression.Constant(2); // 声明常量
            ConstantExpression left = Expression.Constant(544);// 声明常量
            BinaryExpression plus = Expression.Add(left, right);// 声明运算关系
            //构建表达式目录树   ,后面 的 ParameterExpression[] 为空表示参数为空
            Expression<Func<int>> express = Expression.Lambda<Func<int>>(plus,new ParameterExpression[]{ });

复杂一点:

以上面的快捷方式为目的拼接:

代码:

            Expression<Func<int, int, int>> exp = (x, y) => x * y +x+y+ 2;  //快捷方式

            //声明参数与常量
            var param1 = Expression.Parameter(typeof(int), "x");
            var param2 = Expression.Parameter(typeof(int), "y");
            var constant = Expression.Constant(2);

            //创造关系
            var multiply = Expression.Multiply(param1, param2);
            var plus = Expression.Multiply(multiply, param1);
            var plus1 = Expression.Multiply(plus, param2);
            var plus2 = Expression.Multiply(plus1, constant);

            //构建表达式目录树
            Expression<Func<int, int, int>> exp1 = Expression.Lambda<Func<int, int, int>>
                 (plus2, new ParameterExpression[] { param1, param2 });

            //转换为委托并执行
            Console.WriteLine(exp1.Compile().Invoke(456, 123));
            Console.Read();

以上都是加减乘除的 表达式目录树  在 Linq To Sql 应用中经常是如下格式的或者更复杂:

上面的是目标 表达式目录树的 以下我们自己实现:

代码:

//普通声明
            ParameterExpression x = Expression.Parameter(typeof(Company), "x");
            ConstantExpression constant = Expression.Constant("3");

            PropertyInfo IdProp = typeof(Company).GetProperty("Id");//Id 属性
            Expression IdExp = Expression.Property(x, IdProp);  //获取x与Id的关系
            MethodInfo toString = typeof(int).GetMethod("ToString",new Type[] { }); //获取 ToString 方法
            Expression ToStringExp = Expression.Call(IdExp, toString);   //获取Id与 ToString   的关系
            MethodInfo equals = typeof(string).GetMethod("Equals",new Type[] { typeof(string) }); //获取Equals
            Expression EqualsExp = Expression.Call(ToStringExp, equals, new Expression[] { constant }); //获取 string 与 Equals 的关系

            Expression<Func<Company, bool>> exp1 = Expression.Lambda<Func<Company, bool>>(EqualsExp, x);  //建立表达式目录树

            var res = exp1.Compile()(new Company() { Id = 5, Name = "王麻子" });//从表达式目录树中获取委托

我们自己手写 表达式目录树的目的是什么?这么累的玩意

为了实现动态

看一下远古拔版本的拼接条件:

到了 Linq To Sql 时代,再看看表达式目录树怎么拼接:这里的 exp 下面的会覆盖上面的,没有办法 做到 && 的结果,如果一一列举各种情况那会很累

还有第二种方案:这种方案会一直暴露 dbset 即 Company 表 很容易发生可怕的事,这是不知道怎么拼装,无奈的做法

所有我们需要让 表达式目录树 有 Or 和 And

And的初步实现:

//目标
               // Expression<Func<Company, bool>> exp = x => x.Name.Equals("Qal") && x.Id > 5;

                //声明参数与常量
                ParameterExpression x = Expression.Parameter(typeof(Company),"x");
                ConstantExpression constant = Expression.Constant("Qal");
                ConstantExpression int5 = Expression.Constant(5);

                //x.Name.Equals("Qal")
                PropertyInfo NameProp = typeof(Company).GetProperty("Name");
                var NameExp = Expression.Property(x, NameProp);
                MethodInfo equals = typeof(string).GetMethod("Equals");
                var equalsExp = Expression.Call(NameExp, equals, constant);

                //x.Id > 5;
                PropertyInfo IdProp = typeof(Company).GetProperty("Id");
                var IdExp = Expression.Property(x, IdProp);
                var GreaterThenExp = Expression.GreaterThan(IdExp,int5);

                var body = Expression.AndAlso(equalsExp, GreaterThenExp);// 拼接两个条件的表达式目录树
                // 构建表达式目录树
                Expression<Func<Company, bool>> exp1 = Expression.Lambda<Func<Company, bool>>(body, new ParameterExpression[] {x});

                exp1.Compile()(new Company() {Id =10,Name= "Qal" });

以上没有填完的坑待续....................

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
C# 中的表达式目录树(Expression Tree)是一个抽象语法树(AST),可以表示一个 C# 表达式的结构和含义。它们提供了一种将代码表示为数据的方式,可以用于编写动态查询、ORM 映射、编译器、代码生成器等工具。 表达式目录树是由 Expression 类型的对象组成的,每个对象都代表了一个 C# 表达式的一部分。例如,一个二元运算符表达式可以表示为一个 BinaryExpression 类型的对象,它包含了左右操作数和运算符等信息。 表达式目录树可以通过编写 Lambda 表达式来创建。Lambda 表达式是一种匿名函数,可以将其编译成表达式目录树。例如,以下代码创建了一个表示加法的表达式目录树: ``` Expression<Func<int, int, int>> addExpr = (x, y) => x + y; ``` 这个表达式目录树表示了一个接受两个 int 类型参数并返回 int 类型结果的函数,函数体是 x + y。 表达式目录树也可以用于动态构建 LINQ 查询。例如,以下代码构建了一个查询,查询所有 age 大于 18 的人: ``` var people = new List<Person> { ... }; var paramExpr = Expression.Parameter(typeof(Person), "p"); var agePropExpr = Expression.Property(paramExpr, "Age"); var ageConstExpr = Expression.Constant(18, typeof(int)); var greaterThanExpr = Expression.GreaterThan(agePropExpr, ageConstExpr); var lambdaExpr = Expression.Lambda<Func<Person, bool>>(greaterThanExpr, paramExpr); var query = people.AsQueryable().Where(lambdaExpr); ``` 这个代码通过表达式目录树构建了一个 Lambda 表达式,查询所有 age 大于 18 的人。其中,Expression.Parameter() 方法创建了一个表示 Person 类型的参数,Expression.Property() 方法创建了一个表示 Age 属性的表达式Expression.Constant() 方法创建了一个表示常量值的表达式Expression.GreaterThan() 方法创建了一个表示大于运算的表达式Expression.Lambda() 方法将这些表达式组合成一个 Lambda 表达式表达式目录树可以在编译时或运行时进行解析和执行。例如,以下代码编译并执行了一个表示加法的表达式目录树: ``` var addExpr = Expression.Add(Expression.Constant(1), Expression.Constant(2)); var addFunc = Expression.Lambda<Func<int>>(addExpr).Compile(); var result = addFunc(); // 3 ``` 这个代码创建了一个表示加法的表达式目录树,然后将其编译成一个函数(addFunc),最后执行这个函数得到结果(result)。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值