Expression 表达式目录树一

这里有两段代码:

Expression 表达式目录树一_第1张图片

看一下 Where 的参数

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

Expression 表达式目录树一_第2张图片

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

Expression 表达式目录树一_第3张图片

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

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

Expression 表达式目录树一_第4张图片

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

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

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

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

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

 

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

最简版:2+5

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

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

Expression 表达式目录树一_第5张图片

复杂一点:

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

Expression 表达式目录树一_第6张图片

代码:

            Expression> 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> exp1 = Expression.Lambda>
                 (plus2, new ParameterExpression[] { param1, param2 });

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

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

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

Expression 表达式目录树一_第7张图片

代码:

//普通声明
            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> exp1 = Expression.Lambda>(EqualsExp, x);  //建立表达式目录树

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

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

为了实现动态

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

Expression 表达式目录树一_第8张图片

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

Expression 表达式目录树一_第9张图片

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

Expression 表达式目录树一_第10张图片

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

And的初步实现:

//目标
               // Expression> 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> exp1 = Expression.Lambda>(body, new ParameterExpression[] {x});

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

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

 

你可能感兴趣的:(C#)