接续[上篇之预告]
本篇来讲讲,如何根据前面设计的查询描述器构造出可执行的表达式。正如标题所示,实现手段将采用Expression Lambda技术。
先来看看主角System.Linq.Expressions.Expression
长什么样,都有些什么东西,能做什么。 先看看它的类图:
System.Linq.Expressions.ConstantExpression 常量
System.Linq.Expressions.DefaultExpression 默认值
System.Linq.Expressions.IndexExpression 索引
System.Linq.Expressions.MemberExpression 成员(属性或字段)
System.Linq.Expressions.MethodCallExpression 方法调用
System.Linq.Expressions.ParameterExpression 参数
System.Linq.Expressions.UnaryExpression 一元运算
System.Linq.Expressions.BinaryExpression 二元运算
System.Linq.Expressions.LambdaExpression 委托
我们主要使用Expression
这个类,它包含各种节点类型的 static
工厂方法。特别是以下这些方法,对应了查询需要用到的逻辑、比较、数学,等各种运算操作。
逻辑运算 | |
---|---|
AndAlso(Expression, Expression) | 表示And逻辑运算 |
OrElse(Expression, Expression) | 表示Or逻辑运算 |
比较运算 | |
LessThan(Expression, Expression) | 表示小于:”<" |
LessThanOrEqual(Expression, Expression) | 表示大于等于:“<=" |
GreaterThan(Expression, Expression) | 表示大于:”>“ |
GreaterThanOrEqual(Expression, Expression) | 表示大等于:”>=” |
Equal(Expression, Expression) | 表示等于:”=“ |
NotEqual(Expression, Expression) | 表示不等于:”!=” |
IsTrue(Expression) | 测试表达式结果是否为“True” |
IsFalse(Expression) | 测试表达式结果是否为“False” |
Not(Expression) | 表示”Not” |
数学运算 | |
Add(Expression, Expression) | 加法 |
Subtract(Expression, Expression) | 减法 |
Multiply(Expression, Expression) | 乘法 |
Divide(Expression, Expression) | 除法 |
Modulo(Expression, Expression) | 模除 |
Power(Expression, Expression) | 幂运算 |
一些操作 | |
Parameter(Type) | 包装一个类型为Type的参数 |
Call(Expression, MethodInfo, Expression, Expression) | 包装一个方法调用 |
Bind(MemberInfo, Expression) | 包装一个成员绑定,(属性或字段) |
Quote(Expression) | 包装一个括号 |
MakeUnary(ExpressionType, Expression, Type) | 包装一个一元运算 |
MakeBinary(ExpressionType, Expression, Expression) | 包装一个二元运算 |
TypeAs(Expression, Type) | 包装一个显式引用或装箱转换,其中如果转换失败则提供“null”。 |
Coalesce(Expression, Expression, LambdaExpression) | 包装表示给定转换函数的聚结操作。 |
变量、常量、字段、属性 | |
Default(Type) | 包装一个指定类型的默认值 |
Constant(Object, Type) | 包装一个常量 |
Assign(Expression, Expression) | 赋值操作 |
Variable(Type, String) | 包装一个变量定义 |
Property(Expression, MethodInfo) | 包装一个属性 |
Field(Expression, FieldInfo) | 包装一个字段 |
PropertyOrField(Expression, String) | 包装一个指定名称的字段或属性 |
要的就是这结果 | |
Lambda(Expression, ParameterExpression[]) | 包装一个委托,带有一个参数表达式数组。 |
以上仅列出了一部分,它涵盖了全部可能要使用到的函数,语句,欲详细了解可以直接乘坐火箭到微软官方网站查看。
这此函数或功能是有了,如何使用呢?来看个例子:将SQL
:Table1.A > 5 and Table1.B=3
,转成(Table1)=>Table1.A > 5 && Table1.B==3
;
在Expression
的世界里一切都是Expression
。因此首先要将Table1
、A
、5
、B
、 3
先包装成Expression
:
- 开干之前先谈个对象
//实体类: public class Table { public int A; public int B; }
- 然后包装各种
Expression
//将Table1包装成ParameterExpression: var p=Expression.Parameter(typeof(Table1),"Table1"); //将5、3这两个常量包装成ConstantExpression: var num5=Expression.Constant(5,typeof(int)); var num3=Expression.Constant(3,typeof(int)); //将两个属性包装成MemberExpression。 var a=Expression.PropertyOrField(p,"A") var b=Expression.PropertyOrField(p,"B") //构造Table1.A>5: var gt=Expression.GreaterThen(a,num5); //构造Table1.A=3: var eq=Expression.Equal(b,num3);
- 再构造两个比较式
//构造Table1.A>5: var gt=Expression.GreaterThen(a,num5); //构造Table1.A=3: var eq=Expression.Equal(b,num3);
- 加上逻辑
And
将两个比较式连接起来
//构造Table1.A>5 && Table1.A=3 var exp=Expression.AndAlso(gt,eq);
- 结果就要出来了
//结果就获得了: var lambda=Expression.Lambda()
- 来来来,测试一下康康接果:
/*===============来来来,测试一下:===============*/ var f=lambda.Compile(); var x=f.DynamicInvoke(new Table(){A=6,B=3}); var y = f.DynamicInvoke(new Table() { A = 2, B = 3 }); Console.WriteLine("x:{0}\ny:{1}",x,y); Console.WriteLine("Lambda:{0}",lambda.ToString()); /*输出: 结果对吗?我也不知道,我撸得这么辛苦,先让电脑休息一下,各位看官只要Ctrl+C,Ctrl+V就可以看到了. */
- OK,其它各种操作,只要依葫芦画瓢便大功可成! 先爽一下!
- 好,暂且爽到这里,欲看如何把括号弄成俄罗斯套娃,且看下回分解.
- 随手点个赞,让我也爽爽,可好!