旌磅箱 发表于 昨天 19:45

基于Expression Lambda表达式树的通用复杂动态查询构建器——《构思篇二》已开源

接续[上篇之预告]
本篇来讲讲,如何根据前面设计的查询描述器构造出可执行的表达式。正如标题所示,实现手段将采用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)表示小于:"“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,其它各种操作,只要依葫芦画瓢便大功可成! 先爽一下!
[*]好,暂且爽到这里,欲看如何把括号弄成俄罗斯套娃,且看下回分解.
[*]随手点个赞,让我也爽爽,可好!

来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
页: [1]
查看完整版本: 基于Expression Lambda表达式树的通用复杂动态查询构建器——《构思篇二》已开源