Lamda Expression
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的更多相关文章
- 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 ...
- Expression Tree Basics 表达式树原理
variable point to code variable expression tree data structure lamda expression anonymous function 原 ...
- 论C#未来发展
近日M#的消息令江湖再次起了波澜.大家知道,.NET已经进入了瓶颈期.这个消息又让偶有所期待,趁此机会发表一下个人的展望,对C#或者其继任者,不管是M#还是X#. 一.语法特性 1. using引入类 ...
- 数学符号π (Pi)、Σ(Capital Sigma)、μ (Mu) 、σ(sigma)、∏(capital pi), ∫(Integral Symbol)的来历
1.π (Pi; periphery/周长) March 14 marks Pi Day, the holiday commemorating the mathematical constant π ...
- 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 ...
- 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 ...
- Python 与 Javascript 之比较
最近由于工作的需要开始开发一些Python的东西,由于之前一直在使用Javascript,所以会不自觉的使用一些Javascript的概念,语法什么的,经常掉到坑里.我觉得对于从Javascript转 ...
- Unity在WPF中的应用
1. 本文的实现类继承于IRepository using System; using System.Linq; using System.Linq.Expressions; using Zhang. ...
- [No000012E]WPF(6/7):概念绑定
WPF 的体系结构,标记扩展,依赖属性,逻辑树/可视化树,布局,转换等.今天,我们将讨论 WPF 最重要的一部分——绑定.WPF 带来了优秀的数据绑定方式,可以让我们绑定数据对象,这样每次对象发生更改 ...
随机推荐
- 小甲鱼Python第二十一讲课后习题
测试题: 0. 递归在编程上的形式是如何表现的呢? 在编程上,递归表现为函数调用本身这么一个行为. 1. 递归必须满足哪两个基本条件? 一. 函数调用自身二. 设置了正 ...
- target和currentTarget
event.target返回触发事件的元素 event.currentTarget返回绑定事件的元素 1 <ul id="ul">ul 2 <li>li ...
- Linux 中进程的管理
Linux 的进程信号 1 HUP 挂起 2 INT 中断 3 QUIT 结束运行 9 KILL 无条件终止 11 SEGV 段错误 15 TERM 尽可能终止 17 STOP 无条件终止运 ...
- c语言二级指针内存模型
第一种: 指针数组作为输入参数 char *myArray[] = {"aaaaaa", "ccccc", "bbbbbb", " ...
- 5m21d缓冲区溢出学习笔记
mysql链接字符串函数 concat(str1,str2) concat_ws(separator,str1,str2....) group_concat(str1,str2....) mysql的 ...
- 【Java】递归递推的应用
利用阶乘公式来计算组合式: 程序设计思想: 根据公式来计算组合数的大小,从键盘输入n,k的值,设计一个计算阶乘的大小,如果输入的数a为1或0,则直接return 1,否则运用递归,计算a-1的阶乘,直 ...
- 学习ActiveMQ(四):spring与ActiveMQ整合
在上一篇中已经怎么使用activemq的api来实现消息的发送接收了,但是在实际的开发过程中,我们很少使用activemq直接上去使用,因为我们每次都要创建连接工厂,创建连接,创建session... ...
- keras训练cnn模型时loss为nan
keras训练cnn模型时loss为nan 1.首先记下来如何解决这个问题的:由于我代码中 model.compile(loss='categorical_crossentropy', optimiz ...
- 讨论mui 的 mui.init 与 mui.plusReady
先来看一段代码 (function(m, doc) { mui.plusReady(function(){ var self = plus.webview.currentWebview(); olti ...
- linux内核态和用户态的信号量
在Linux的内核态和用户态都有信号量,使用也不同,简单记录一下. 1> 内核信号量,由内核控制路径使用.内核信号量是struct semaphore类型的对象,它在中定义struct sema ...