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. (转)谈谈用ASP.NET开发的大型网站有哪些架构方式(成本)

    在上篇文章里(http://www.cnblogs.com/ms0017/archive/2011/07/26/2117676.html),列举了国内外用ASP.NET开发的大型网站有哪些.最后提到了 ...

  2. GMA Round 1 新程序

    传送门 新程序 程序框图如图所示,当输入的n=时,输出结果的ans是多少? 容易看出该程序求n以内质数个数,50以内有15个. 定位:简单题

  3. 在Linux下开发多语言软件(gettext解决方案)

    最近的项目出现了一个bug.项目是基于一个已有的成熟开源软件之上做修改的,新写了加解密库,用于为该成熟开源软件增添加解密功能.功能增加完成后效果都很好,可是就是中文出不来了,也就是说没办法自适应多语言 ...

  4. css display:flex 属性

    一:display:flex 布局 display:flex 是一种布局方式.它即可以应用于容器中,也可以应用于行内元素.是W3C提出的一种新的方案,可以简便.完整.响应式地实现各种页面布局.目前,它 ...

  5. [ERROR] Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.1:compile (default-compile) on project triage: Compilation failure [ERROR] No compiler is provided in this environment.

    [ERROR] Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.1:compile (default-c ...

  6. ol图层支持的数据源

    ol.source.BingMaps,必应地图的数据: ol.source.Cluster,聚族矢量数据: ol.source.ImageCanvas,数据来源是一个canvas元素,其中数据是图片: ...

  7. Python Learning - Three

    1. Set  Set is a collection which is unordered and unindexed. No duplicate members In Python sets ar ...

  8. 如何从日期对象python获取以毫秒(秒后3位小数)为单位的时间值?

    要在python中,要获取具有毫秒(秒后3位小数)的日期字符串,请使用以下命令: %f 显示毫秒 import datetime # 获得当前时间 now=datetime.datetime.now( ...

  9. 关于Spring事物的面试题

    https://blog.csdn.net/h294590501/article/details/80386000 数据库事务和Spring事务是一般面试都会被提到,很多朋友写惯了代码,很少花时间去整 ...

  10. 使用npm 下载 cnpm

    在vue终端使用npm 1. 下载安装node.js 在node.js中有集成npm 2. 可以在终端中使用 node -v / npm -v 来查看安装的node/npm 的版本号 使用npm 安装 ...