现有如下实体

    public class User
{
public int Id { get; set; }
public string Name { get; set; }
}

根据这个实体创建一个Iqueryable<User>对象queryList

List<User> dList = new List<User> {
new User{Id=,Name="zhansan" },
new User{Id=,Name="lisi" },
new User{Id=,Name="wangwu" },
new User{Id=,Name="zhaoliu" },
new User{Id=,Name="sunqi" },
};

dList的where方法需要一个Func<User, bool> whereFunc参数来进行数据过滤,但很多时候whereFunc是动态的,我的查询条件有时是u=>u.Id==1||u.Id==2,有时条件为u=>u.Id==1||u.Id==2&&u.Name=="lisi"

如此看来条件是不固定的并且属性组合方式多种多样,这样就迫切地需要一种方法可以动态地拼接表达式

如下两个表达式,将演示如何和为一个表达式

Expression<Func<User, bool>> ef = u => u.Id ==  || u.Id == ;
Expression<Func<User, bool>> ef2 = y => y.Name == "lisi";

首先创建类MyVisitor

    public class MyVisitor : ExpressionVisitor
{
Dictionary<ParameterExpression, ParameterExpression> map;
public MyVisitor(Dictionary<ParameterExpression, ParameterExpression> map)
{
this.map = map;
}
protected override Expression VisitParameter(ParameterExpression node)
{
return map[node];
}
}

此类继承自ExpressionVisitor类,此类是expression表达式的工具类,可对expression表达式内部的成员进行替换

首先我自定义了构造函数传入一个字典对象。作用在后面解释

然后我重写了VisitorParameter方法,此方法的参数node即为要修改的expression的参数部分,你的expression有多少个参数就会顺序触发此方法并传入相应参数

准备工作到此就结束了,接下来是拼接过程

var pl = ef.Parameters;
var dic = ef.Parameters.Select((f, i) => new { f, f2 = ef2.Parameters[i] }).ToDictionary(p => p.f2, p => p.f);
MyVisitor myVisitor = new MyVisitor(dic);
var body = myVisitor.Visit(ef2.Body);
var finalBody = Expression.And(ef.Body, body);
var fu = Expression.Lambda<Func<User, bool>>(finalBody, pl).Compile();
var re= dList.Where(fu).ToList();

首先得到字典dic其key为ef2的参数列表,值为ef的参数列表

然后创建刚才自定义的MyVisitor类的对象,并传入字典dic

之后调用myVisitor的Visit方法传入ef2的Body部分,此时根据MyVisitor中对VisitParameter的重写可知

protected override Expression VisitParameter(ParameterExpression node)
{
return map[node];
}

在内部myVisitor对传入的ef2.Body的每一个参数查询字典,并返回值,此值即为ef的参数值,此处就将ef2的参数都替换为ef1的参数了

接下来就是两个表达式的拼接部分

var body = myVisitor.Visit(ef2.Body);
var finalBody = Expression.And(ef.Body, body);
var fu = Expression.Lambda<Func<User, bool>>(finalBody, pl).Compile();

将两个表达式的body部分用and连接,并且使用pl为参数(这很重要,前面做这么多就是为了把ef2的body部分的参数更换为ef的参数)

这样就得到了拼接后的func,传入where作为条件进行查询

var re= dList.Where(fu).ToList();

  

使用ExpressionVisitor进行lambadaExpression的动态拼接的更多相关文章

  1. Lambda表达式动态拼接(备忘)

    EntityFramework动态组合Lambda表达式作为数据筛选条件,代替拼接SQL语句 分类: C# Lambda/Linq Entity Framework 2013-05-24 06:58 ...

  2. EF 拉姆达 动态拼接查询语句

    EF 动态拼接查询语句 using System; using System.Collections.Generic; using System.IO; using System.Linq; usin ...

  3. 初识Mybatis框架,实现增删改查等操作(动态拼接和动态修改)

    此第一次接触Mybatis框架确实是有点不适应,特别是刚从Hibernate框架转转型过来,那么为什么要使用Mybatis框架,Mybatis框架和Hibernate框架又有什么异同呢? 这个问题在我 ...

  4. mybatis 使用记录(二) 动态拼接查询条件

    2016-12-16 阅读项目代码时,在项目的xml文件中发现如下写法: SELECT student_user_id FROM tbr_student_class WHERE 1=1 <if ...

  5. 动态拼接 sql的时候 里面 如果有变量的话 按上面的方式进行处理

    set @Sql_Sql = N' select top 1 @m_zw=zw,@m_zh=temp from ket where zd=''ddd'' ' print @Sql_Sql EXEC s ...

  6. 分享动态拼接Expression表达式组件及原理

    前言 LINQ大家都知道,用起来也还不错,但有一个问题,当你用Linq进行搜索的时候,你是这样写的 var query = from user in db.Set<User>()      ...

  7. 表达式树动态拼接lambda

    动态拼接lambda表达式树   前言 最近在优化同事写的代码(我们的框架用的是dapperLambda),其中有一个这样很普通的场景——界面上提供了一些查询条件框供用户来进行过滤数据.由于dappe ...

  8. 动态拼接lambda表达式树

    前言 最近在优化同事写的代码(我们的框架用的是dapperLambda),其中有一个这样很普通的场景——界面上提供了一些查询条件框供用户来进行过滤数据.由于dapperLambda按条件查询时是传入表 ...

  9. vue获得当前页面URL动态拼接URL复制邀请链接方法

    vue获得当前页面URL动态拼接URL复制邀请链接方法 当前页面完整url可以用 location.href路由路径可以用 this.$route.path路由路径参数 this.$route.par ...

随机推荐

  1. android studio 怎么将项目打包成apk文件

    1.Build -> Generate Signed APK...,打开如下窗口 2.假设这里没有打过apk包,点击Create new,窗口如下 这里只要输入几个必要项 Key store p ...

  2. js动态增加秒数(自动,手动)

    //获取当前的日期及时间Date var myDate = new Date();      myDate.getYear();        //获取当前年份(2位)      myDate.get ...

  3. Error creating document instance

    Error creating document instance.  Cause: org.xml.sax.SAXParseException; lineNumber: 52; columnNumbe ...

  4. 在H3C交换机上开通一个VLAN并且开通一个端口ping通它

    <H3C>system-view System View: return to User View with Ctrl+Z. [H3C]interface vlan-interface 2 ...

  5. Merge使用

    Role r = new Role(); r.setName("TEST"); r.setDescription("123"); r.setLevel(2); ...

  6. BootLoader--改进(基于2440)

    BootLoader--改进 之前编写的Bootloader启动内核时间使用差不多7秒钟的时间,大多都是用在CPU将内核从Nandflash读取到SDRam中,故首先想到的方法是改变CPU时钟频率. ...

  7. Ambari安装之安装并配置Ambari-server(三)

    前期博客  Ambari安装之部署本地库(镜像服务器)(二) 安装并配置Ambari-server (1)检查仓库是否可用 [hadoop@ambari01 yum.repos.d]$ pwd /et ...

  8. css3 变换 transform(2D)

    一.transform变换 可做拉伸.压缩.旋转.偏移的效果.需加各个浏览器前缀. 二.transform-origin 为transform属性值的基点,默认值为元素的中心位置,即以元素左上角为坐标 ...

  9. 号称精通Java的你,是否真的名副其实

    慎用精通 随着猎头行业的兴盛,一些应聘者往往可以从猎头那得到一些注意事项和过往经验.比如,在简历中切不可随意用上"精通"二字,尤其对于刚入职场的小伙伴. 因为,对于应聘者写上精通和 ...

  10. [C++]智能指针的实现与使用

    智能指针 智能指针是当我们在使用对象时,有时会把对象的内存分配在堆上忘记释放,导致内存泄露,并且当多个指针共享同一个对象的内存时,容易出现重复释放内存,导致错误. 我们针对所需要共享的对象,手动完成一 ...