Lambda表达式树解析(下)包含自定义的provider和查询
概述
前面章节,总结了Lambda树的构建,那么怎么解析Lambda表达式树那?Lambda表达式是一种委托构造而成,如果能够清晰的解析Lambda表达式树,那么就能够理解Lambda表达式要传递的正式意图。解析Lambda表达式树意义很大,比如我们用的EF框架、Rafy框架,里面封装了大量的Lambda查询表达式,通过解析表达式转换成SQL语句,即可以查询数据库,将数据呈现给前台用户;
Lambda表达式树解析
下面代码块是标识Express各个节点的信息,ExpressionType.Call标识表达式中含有方法调用,常用到该类型的3个参数为:Method.DeclaringType和Argument和object。ExpressionType.Quote标识表达式中含有一元表达式,常用到的参数是Operand,里面放置了Lamble具体表达式。

public string AnalysisExpression(Expression exp)
{
string TextSql = "";
switch (exp.NodeType)
{
case ExpressionType.Call:
{
MethodCallExpression mce = exp as MethodCallExpression;
Console.WriteLine("The Method Is {0}", mce.Method.Name);
Console.WriteLine("The Method TypeOf {0}", mce.Method.DeclaringType);
if (mce.Method.DeclaringType == typeof(string))
{
break;
}
if (mce.Method.DeclaringType != typeof(Queryable)){
break;
}
for (int i = 0; i < mce.Arguments.Count; i++)
{ TextSql+=AnalysisExpression(mce.Arguments[i]);
}
}
break;
case ExpressionType.Quote:
{
UnaryExpression ue = exp as UnaryExpression;
TextSql += AnalysisExpression(ue.Operand);
}
break;
case ExpressionType.Lambda:
{
LambdaExpression le = exp as LambdaExpression;
AnalysisExpression(le.Body);
TextSql+= ExpressTreeAnalysis.GetSqlByExpression(le.Body);
}
break;
case ExpressionType.AndAlso:
case ExpressionType.OrElse:
case ExpressionType.Equal:
{
BinaryExpression be = exp as BinaryExpression;
Console.WriteLine("The Method Is {0}", exp.NodeType.ToString());
TextSql += AnalysisExpression(be.Left);
TextSql += AnalysisExpression(be.Right);
}
break;
case ExpressionType.Constant:
{
ConstantExpression ce = exp as ConstantExpression;
Console.WriteLine("The Value Type Is {0}", ce.Value.ToString());
}
break;
case ExpressionType.Parameter:
{
ParameterExpression pe = exp as ParameterExpression;
Console.WriteLine("The Parameter Is {0}", pe.Name);
}
break;
default:
{
Console.Write("UnKnow");
}
break;
}
return TextSql;
}

由于自定义集合实现IQueryable和IQueryProvider来自定义查询项
实现IQuable定义的类:

public class BlogQueryable<T> : IQueryable<T>
{
BlogQueryProvider provider;
Expression expression; public BlogQueryable(BlogQueryProvider provider)
{
if (provider == null)
{
throw new ArgumentNullException("provider");
}
this.provider = provider;
this.expression = Expression.Constant(this);
} public BlogQueryable(BlogQueryProvider provider, Expression expression)
{
this.provider = provider;
this.expression = expression;
}
public Type ElementType
{
get
{
return typeof(T);
}
} public Expression Expression
{
get
{
return expression;
}
} public IQueryProvider Provider
{
get
{
return provider;
}
} public IEnumerator<T> GetEnumerator()
{
return ((IEnumerable<T>)this.provider.Execute(this.expression)).GetEnumerator();
} IEnumerator IEnumerable.GetEnumerator()
{
return ((IEnumerable)this.provider.Execute(this.expression)).GetEnumerator();
} public void Where2(Expression<Func<T, bool>> func)
{
string TextSql = ExpressTreeAnalysis.GetSqlByExpression(func.Body);
}
}

实现IQueryProvider接口的类,CreateQuery解析表达式树而Execute则是执行解析后的SQL语句,查询数据,填充list集合:

public class BlogQueryProvider : IQueryProvider
{ public IQueryable CreateQuery(Expression expression)
{
Type elementType = expression.Type;
try
{
return (IQueryable)Activator.CreateInstance(typeof(BlogQueryable<>).MakeGenericType(elementType), new object[] { this, expression });
}
catch(TargetInvocationException tie)
{
throw tie.InnerException;
}
} public IQueryable<TElement> CreateQuery<TElement>(Expression expression)
{ //string TextSql= ExpressTreeAnalysis.GetSqlByExpression(((Expression)(expression as MethodCallExpression).Arguments[1]).bo);
//Console.WriteLine(TextSql);
AnalysisExpression(expression);
return new BlogQueryable<TElement>(this, expression);
} public object Execute(Expression expression)
{
return this.Execute2<object>(expression);
} public TResult Execute<TResult>(Expression expression)
{
return (TResult)this.Execute2<TResult>(expression);
} public TResult Execute2<TResult>(Expression expression)
{
return (TResult)Activator.CreateInstance(typeof(TResult));
}
}

具体下面即可使用查询

public void MyTestMethod()
{
Catagory cag = new Catagory("四大名著点评"); IList<Blog> Blogs = new List<Blog>();
Blog bok = new Blog() { Title = "红楼梦", Conent = "红楼梦书籍不错",
User = new Author() { UserName = "曹雪芹", BirefInfor = "中国清代著名作家" } };
bok.Catagories.Add(cag);
bok.Catagories.Add(new Catagory("红楼梦专栏"));
Blogs.Add(bok); Blog bok2 = new Blog() { Title = "三国演义", Conent = "三国鼎立时期的描述",
User = new Author() { UserName = "罗贯中", BirefInfor = "中国元末明初著名作家" } };
bok2.Catagories.Add(cag);
bok2.Catagories.Add(new Catagory("三国演义专栏"));
Blogs.Add(bok2); Blog bok3 = new Blog() { Title = "西游记", Conent = "西游记讲述四个徒弟和一个师傅取经事情",
User = new Author() { UserName = "吴承恩", BirefInfor = "中国明代杰出的小说家" } };
bok2.Catagories.Add(cag);
bok2.Catagories.Add(new Catagory("西游记专栏"));
Blogs.Add(bok3); Blog bok4 = new Blog() { Title = "水浒传", Conent = "描述梁山好汉劫富济贫的故事",
User = new Author() { UserName = "施耐庵", BirefInfor = "中国明代杰出的小说家" } };
bok2.Catagories.Add(cag);
bok2.Catagories.Add(new Catagory("水浒传专栏"));
Blogs.Add(bok4); BlogQueryProvider Provider = new BlogQueryProvider();
BlogQueryable<Blog> Quble = new BlogQueryable<Blog>(Provider); var t2 = Quble.Where(p => p.Title == "123" && p.Conent.Contains("水浒"));
}

后续:针对解析Lambda表达式树成SQL,本人也是刚刚入门,至于完全要解析成SQL,还需要研究......
https://www.cnblogs.com/xibei666/p/6858299.html
Lambda表达式树解析(下)包含自定义的provider和查询的更多相关文章
- Lambda表达式树解析(下)
概述 前面章节,总结了Lambda树的构建,那么怎么解析Lambda表达式树那?Lambda表达式是一种委托构造而成,如果能够清晰的解析Lambda表达式树,那么就能够理解Lambda表达式要传递的正 ...
- Lambda表达式树构建(上)
概述 Lambda是C#常用的语句,采用委托等方式,来封装真实的代码块.Lambda其实就是语法糖,是一个匿名函数,是一种高效的类似于函数式编程的表达式,Lambda简化了开发中需要编写的代码量.它可 ...
- 干货!表达式树解析"框架"(1)
最新设计请移步 轻量级表达式树解析框架Faller http://www.cnblogs.com/blqw/p/Faller.html 关于我和表达式树 其实我也没有深入了解表达式树一些内在实现的原理 ...
- 轻量级表达式树解析框架Faller
有话说 之前我写了3篇关于表达式树解析的文章 干货!表达式树解析"框架"(1) 干货!表达式树解析"框架"(2) 干货!表达式树解析"框架" ...
- 动态拼接lambda表达式树
前言 最近在优化同事写的代码(我们的框架用的是dapperLambda),其中有一个这样很普通的场景——界面上提供了一些查询条件框供用户来进行过滤数据.由于dapperLambda按条件查询时是传入表 ...
- 将简单的lambda表达式树转为对应的sqlwhere条件
1.Lambda的介绍 园中已经有很多关于lambda的介绍了.简单来讲就是vs编译器给我带来的语法糖,本质来讲还是匿名函数.在开发中,lambda给我们带来了很多的简便.关于lambda的演变过程可 ...
- 程序猿修仙之路--数据结构之你是否真的懂数组? c#socket TCP同步网络通信 用lambda表达式树替代反射 ASP.NET MVC如何做一个简单的非法登录拦截
程序猿修仙之路--数据结构之你是否真的懂数组? 数据结构 但凡IT江湖侠士,算法与数据结构为必修之课.早有前辈已经明确指出:程序=算法+数据结构 .要想在之后的江湖历练中通关,数据结构必不可少. ...
- 用lambda表达式树替代反射
本节重点不讲反射机制,而是讲lambda表达式树来替代反射中常用的获取属性和方法,来达到相同的效果但却比反射高效. 每个人都知道,用反射调用一个方法或者对属性执行SetValue和GetValue操作 ...
- 干货!表达式树解析"框架"(2)
最新设计请移步 轻量级表达式树解析框架Faller http://www.cnblogs.com/blqw/p/Faller.html 为了过个好年,我还是赶快把这篇完成了吧 声明 本文内容需要有一定 ...
随机推荐
- spring-retry的简单使用
添加Maven依赖: <dependency> <groupId>org.springframework.retry</groupId> <artifactI ...
- [动态库]动态库生成和使用以及Makefile编写
转自:https://www.cnblogs.com/ljtknowns/p/5647793.html 文件目录结构如下 1 dynamiclibapp.c 2 Makefile 3 comm/inc ...
- Android——shape和selector和layer-list的(详细说明 转)
<shape>和<selector>在Android UI设计中经常用到.比如我们要自定义一个圆角Button,点击Button有些效果的变化,就要用到<shape> ...
- unix的sed 用法介绍
sed是一个非交互性性文本编辑器,它编辑文件或标准输入导出的文件拷贝.标准输入可能是来自键盘.文件重定向.字符串或变量,或者是一个管道文件.sed可以随意编辑小或大的文件,有许多sed命令用来编辑.删 ...
- 在eclpse中 一个web project 引用多个 java project 的方法
在开发时,我们会遇到一个需求:模块化.它要求我们把 业务组件进行拆分,分组.把一部分业务功能集中处理,以保证 部分功能块的独立,便于 分配任务到个人,确定人员职责,源代码管理,和发布时重组. 我们尝试 ...
- mysql中varbinary、binary、char、varchar异同
binary 与 varbinary 类型和char与varchar类型是相似的,只是他们存储的是二进制数据,也就是说他们是包含字节流而不是字符流,他们有二进制字符的集合和顺序,他们的对比,排序是基于 ...
- 使用openssl模拟CA和CA证书的签发
使用openssl模拟CA和CA证书的签发 当使用ssl/tls进行加密通信时,必须要有数字证书.若通信只限制在局域网内,可以不向第三方机构申请签发证书,可以通过openssl模拟CA(Cer ...
- 跨域通信--Window.postMessage()
一.跨源通信概述 源:协议.端口号(https默认值433).主机域名(document.domain) 作用:向目标窗口派发MessageEvent消息(四个属性) 兼容参考 MessageEven ...
- jQuery&CSS 顶部和底部固定浮动工具栏 兼容IE6
http://www.cnblogs.com/lhj588/archive/2013/04/02/2994639.html —————————————————————————————————————— ...
- 如何使用Javascript XSLT 处理XML文件(支持Firefox)
最近使用Firefox进行网页的调试,发现有些Javascript XSLT处理XML的语句仅仅支持IE浏览器.而网络中的一些介绍javascript XSLT 处理XML的文章基本上都是依据AJAX ...