找回密码
 立即注册
首页 业界区 业界 基于Expression Lambda表达式树的通用复杂动态查询构建 ...

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

旌磅箱 2025-6-6 19:45:29
接续[上篇之预告]
本篇来讲讲,如何根据前面设计的查询描述器构造出可执行的表达式。正如标题所示,实现手段将采用Expression Lambda技术。
先来看看主角System.Linq.Expressions.Expression 长什么样,都有些什么东西,能做什么。 先看看它的类图:
1.png


  • 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:

  • 开干之前先谈个对象
  1. //实体类:
  2.    public class Table
  3.    {
  4.        public int A;
  5.        public int B;
  6.    }
复制代码
 

  • 然后包装各种Expression
  1.     //将Table1包装成ParameterExpression:
  2.     var p=Expression.Parameter(typeof(Table1),"Table1");
  3.     //将5、3这两个常量包装成ConstantExpression:
  4.     var num5=Expression.Constant(5,typeof(int));
  5.     var num3=Expression.Constant(3,typeof(int));
  6.     //将两个属性包装成MemberExpression。
  7.     var a=Expression.PropertyOrField(p,"A")
  8.     var b=Expression.PropertyOrField(p,"B")
  9.     //构造Table1.A>5:
  10.     var gt=Expression.GreaterThen(a,num5);
  11.     //构造Table1.A=3:
  12.     var eq=Expression.Equal(b,num3);   
  13.    
复制代码
 

  • 再构造两个比较式
  1.   //构造Table1.A>5:
  2.   var gt=Expression.GreaterThen(a,num5);
  3.     //构造Table1.A=3:
  4.     var eq=Expression.Equal(b,num3);   
复制代码
 

  •  加上逻辑And将两个比较式连接起来
  1.     //构造Table1.A>5 && Table1.A=3
  2.     var exp=Expression.AndAlso(gt,eq);
复制代码
 

  •  结果就要出来了
  1. //结果就获得了:
  2.     var lambda=Expression.Lambda()
  3.        
复制代码
 

  • 来来来,测试一下康康接果:
  1.    /*===============来来来,测试一下:===============*/    
  2.    var f=lambda.Compile();
  3.    var x=f.DynamicInvoke(new Table(){A=6,B=3});
  4.    var y = f.DynamicInvoke(new Table() { A = 2, B = 3 });
  5.    Console.WriteLine("x:{0}\ny:{1}",x,y);
  6.    Console.WriteLine("Lambda:{0}",lambda.ToString());          
  7.     /*输出:
  8.     结果对吗?我也不知道,我撸得这么辛苦,先让电脑休息一下,各位看官只要Ctrl+C,Ctrl+V就可以看到了.
  9.     */
复制代码
 

  • OK,其它各种操作,只要依葫芦画瓢便大功可成! 先爽一下!
  • 好,暂且爽到这里,欲看如何把括号弄成俄罗斯套娃,且看下回分解.
  • 随手点个赞,让我也爽爽,可好!

来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
您需要登录后才可以回帖 登录 | 立即注册