Expression<Func<Student, bool>> filter=s=>s.Name.Contains("a") && s.Age>=20;

这样的表达试转换成

Expression<Func<DataRow, bool>> filter = r=>((string)r["Name"]).Contains("a") && ((int)r["Age"])>=20;

也许你会问,干嘛要这样做呢?举个例子,

说DAL里有一个类StudentProvider用于对student进行数据库的增删改查的操作。我们就拿查询来说,查询可以有很多的条件。以往可能会有类似的方法:

public IEnumerable<Student> GetStudentsByName(string name);
public Student GetStudentById(int id);

但是别忘了今天的世界有了Expression,我们应该向这些落后的(别打我,窃以为的)方法说再见了。高颜值的接口当然要写成这样了:

public IEnumerable<Student> GetStudents(Expression<Func<Student, bool>> filter);

于是我们来看看这个方法的实现,

     public IEnumerable<Student> GetStudents(Expression<Func<Student, bool>> filter)
{
using (var connection=new SqlConnection("some connection string"))
{
var selectSql = "SELECT * FROM Student";
using (var adapter = new SqlDataAdapter(selectSql, connection))
{
var ds = new DataSet();
adapter.Fill(ds, "table");
return from raw in ds.Tables["table"].AsEnumerable() select new Student(raw);
}
}
}

实现用到了Linq to DataSet, 其实我们真正想做的是

return from raw in ds.Tables["table"].AsEnumerable().Where(filter) select new Student(raw)

但是问题是Where只接受

Func<DataRow, bool> predicate

到这里,终于明白了为什么要做LambdaExpression变换了吧。

前一篇中我们看到了ExpressionVisitor的强大,这里我们还要用他来解决问题。我们引入一个ConvertMemberToColumnVisitor:

     public class ConvertMemberToColumnVisitor : ExpressionVisitor
{
private readonly Expression _columnOwnerExpression;
private readonly string _memberOwnerName; public ConvertMemberToColumnVisitor(Expression columnOwnerExpression, string memberOwnerName)
{
_columnOwnerExpression = columnOwnerExpression;
_memberOwnerName = memberOwnerName;
} protected override Expression VisitMember(MemberExpression node)
{
var parameterExpression = node.Expression as ParameterExpression;
if (parameterExpression != null && parameterExpression.Name == _memberOwnerName)
{
return Expression.Convert(Expression.Call(_columnOwnerExpression, typeof(DataRow).GetMethod("get_Item", new []{typeof(string)}), Expression.Constant(node.Member.Name)),
((PropertyInfo)node.Member).PropertyType);
} return base.VisitMember(node);
}
}

很简单,很定一个我们要替代成的表达式,当然我们还是用parameter name来匹配所以要给定一个参数名。

有了这个Visitor后,一切问题都简单了:

     public IEnumerable<Student> GetStudents(Expression<Func<Student, bool>> filter)
{
using (var connection=new SqlConnection("some connection string"))
{
var selectSql = "SELECT * FROM Student";
using (var adapter = new SqlDataAdapter(selectSql, connection))
{
var ds = new DataSet();
adapter.Fill(ds, "table"); var p1 = Expression.Parameter(typeof(DataRow), "r");
var converter = new ConvertMemberToColumnVisitor(p1, filter.Parameters[0].Name);
var newExp = converter.Visit(filter);
var lambda = Expression.Lambda<Func<DataRow, bool>>(((LambdaExpression)newExp).Body, p1);
var predicate = lambda.Compile();
return from raw in ds.Tables["table"].AsEnumerable().Where(predicate) select new Student(raw);
}
}
}

Lamda Expression的更多相关文章

  1. Does Lamda expression return value?

    Basically, the compiler does this for you. If you write a lambda as a single statement (and don't in ...

  2. Expression Tree Basics 表达式树原理

    variable point to code variable expression tree data structure lamda expression anonymous function 原 ...

  3. 论C#未来发展

    近日M#的消息令江湖再次起了波澜.大家知道,.NET已经进入了瓶颈期.这个消息又让偶有所期待,趁此机会发表一下个人的展望,对C#或者其继任者,不管是M#还是X#. 一.语法特性 1. using引入类 ...

  4. 数学符号π (Pi)、Σ(Capital Sigma)、μ (Mu) 、σ(sigma)、∏(capital pi), ∫(Integral Symbol)的来历

    1.π (Pi; periphery/周长) March 14 marks Pi Day, the holiday commemorating the mathematical constant π ...

  5. Java learning notes (1):Basic Knowlege points

    Basic Knowlege points: 1: it's necessary that there is only one public class in per .java file 2: .j ...

  6. IMPLEMENTATION - Entity Framework Anti Pattern - High Performance EF

    Good about ORM Developer is free from building T-Sql on the database tier which is not their major a ...

  7. Python 与 Javascript 之比较

    最近由于工作的需要开始开发一些Python的东西,由于之前一直在使用Javascript,所以会不自觉的使用一些Javascript的概念,语法什么的,经常掉到坑里.我觉得对于从Javascript转 ...

  8. Unity在WPF中的应用

    1. 本文的实现类继承于IRepository using System; using System.Linq; using System.Linq.Expressions; using Zhang. ...

  9. [No000012E]WPF(6/7):概念绑定

    WPF 的体系结构,标记扩展,依赖属性,逻辑树/可视化树,布局,转换等.今天,我们将讨论 WPF 最重要的一部分——绑定.WPF 带来了优秀的数据绑定方式,可以让我们绑定数据对象,这样每次对象发生更改 ...

随机推荐

  1. 子集三种生成方法 java

    增量构造法 public class Main1 { static int A[] = new int[1 << 7]; static int da[] = new int[1<&l ...

  2. 3.2station

    题意火车进入,然后要求以最大字典序输出 解题思路:先用一个数组储存当前位置之后最大的数字是什么,然后把已经进站的最后一节火车和还没进站的车的最大值,哪个更大,如果已经进站的更大,那么就先出站,否则就先 ...

  3. tomcat错误The superclass "javax.servlet.http.HttpServlet" was not found on the Java Build Path

    在更换tomcat版本后,原来的项目文件中jsp会出现错误The superclass "javax.servlet.http.HttpServlet" was not found ...

  4. shell变量的使用及输入输出

    1.shell 中变量名可以由字母,数字,下划线组成,但数字不能作为变量名的第一个数字 2.通过赋值符合“=” 来定义一个变量的值 如 myname='zhangjunjie'  #字符串类型,不解析 ...

  5. 配置ssh框架启动tomcat服务器报异常Unable to create requested service [org.hibernate.engine.jdbc.env.spi.JdbcEnvironment]

    在Spring中配置jdbc时,引用的是dbcp.jar包,在db.properties配置文件中,使用了之前的properties配置文件的用户名username(MySql用户名) 然后在启动服务 ...

  6. 十二、JDBC

    day17 JDBC入门 l 导jar包:驱动! l 加载驱动类:Class.forName(“类名”); l 给出url.username.password,其中url背下来! l 使用Driver ...

  7. js的作用域题

    ---恢复内容开始--- 1. var a = 12 function fn() { console.log(a) var a = 45; console.log(a) } fn() 2. funct ...

  8. 如何为Windows XP / Windows7-32bit / Windows7-64bit安装capicom.dll

    原文: http://164.100.181.16/ssdgsap/RegisterDLL.htm 1.根据操作系统的要求下载相应的文件夹安装capicom.dll for Windows XP的步骤 ...

  9. 正版STLINK使用注意

    原文:https://blog.csdn.net/xinghuanmeiying/article/details/78026561 盗版的TVCC是3.3v,可以只用1,7,9,12 正版的TVCC是 ...

  10. AES加密的S盒和逆S盒的推导代码备份(C实现)

    摘取自https://www.cnblogs.com/Junbo20141201/p/9369860.html,感谢原作者的详细解读. #include <stdio.h> ][] = { ...