Expression表达式树(C#)
Lambda表达式:
1.下面举例通过Lambda表达式创建了一个用于验证Name的Func委托。
//通过Lambda表达式创建一个对象的Name属性验证委托
Func<SearchInfo, bool> func = x => x.Name.Equals("");
/// <summary>
/// 测试类
/// </summary>
public class SearchInfo
{
public string Name { get; set; } public string Code { get; set; }
}
2.测试调用, 下面验证 "6" 是否和 "5" 相等, 结果false
//res=false
bool res = func(new SearchInfo() { Name = "" });
那么问题来了, 如果我希望验证的结果不是 "5" 而是其他的内容: "7","9" ...等等呢? ,
那么接下来封装一个Func, 允许自定义验证结果:
public static Func<SearchInfo, bool> Func(string arr)
{
return x => x.Name.Equals(arr); //这一步将Equals中校验的内容进行了参数封装
}
测试代码:
bool f1= Func("")(new SearchInfo() { Name = "" }); //true
bool f2 = Func("")(new SearchInfo() { Name = "" }); //false
bool f3 = Func("")(new SearchInfo() { Name = "" }); //false
如上所示, 我们成功的把Equals中的验证结果封装了起来。但是 !实际应用这还不够,
如果你要校验的不是Name 或是Code, Equals 变成其他 Contains呢?如下:

﹋﹊﹋﹊﹋﹊﹋﹊﹋分割线﹊﹋﹊﹋﹊﹋﹊﹋﹊
Expression(表达式树)
位于 System.Linq.Expressions 命名空间下, 下面介绍如何以上简单的示例创建一个动态的Expression, 类型参数为委托类型:
//
// 摘要:
// 将强类型化的 Lambda 表达式表示为表达式树形式的数据结构。 此类不能被继承。
//
// 类型参数:
// TDelegate:
// 该委托的类型, System.Linq.Expressions.Expression`1 表示。
public sealed class Expression<TDelegate> : LambdaExpression
{
//
// 摘要:
// 编译表达式树由描述为可执行代码的 lambda 表达式,并生成一个委托,表示 lambda 表达式。
//
// 返回结果:
// 类型的委托 TDelegate 表示所描述的已编译的 lambda 表达式 System.Linq.Expressions.Expression`1。
public TDelegate Compile();
//
// 摘要:
// 将生成一个委托,表示 lambda 表达式。
//
// 参数:
// debugInfoGenerator:
// 由编译器用于将标记序列点并添加批注的本地变量的调试信息生成器。
//
// 返回结果:
// 一个包含已编译的版本的 lambda 的委托。
public TDelegate Compile(DebugInfoGenerator debugInfoGenerator);
//
// 摘要:
// 创建一个新的表达式,它类似于此表达式,但使用所提供的子级。 如果所有子级均相同,它将返回此表达式。
//
// 参数:
// body:
// System.Linq.Expressions.LambdaExpression.Body 结果属性。
//
// parameters:
// System.Linq.Expressions.LambdaExpression.Parameters 结果属性。
//
// 返回结果:
// 如果子级未更改,则为此表达式;否则为具有已更新子级的表达式。
public Expression<TDelegate> Update(Expression body, IEnumerable<ParameterExpression> parameters);
protected internal override Expression Accept(ExpressionVisitor visitor);
}
示例(用表达式的形式):
注释: 为了能够了解 Expression<Func<SearchInfo, bool>> lambda = x => x.Name.Equals("5") 这段代码的结构,
接下来用 ILSpy 反编译, 查看到该代码生成了如下:
ParameterExpression parameterExpression = Expression.Parameter(typeof(SearchInfo), "x");
Expression<Func<SearchInfo, bool>> expression = Expression.Lambda<Func<SearchInfo, bool>>(Expression.Call(
Expression.Property(parameterExpression, (MethodInfo)MethodBase.GetMethodFromHandle(ldtoken(get_Name()))),
(MethodInfo)MethodBase.GetMethodFromHandle(ldtoken(Equals())),
new Expression[]
{
Expression.Constant("", typeof(string))
}), new ParameterExpression[]
{
parameterExpression
});
我们分解以上代码(先用数字标识):
1. ParameterExpression parameterExpression = Expression.Parameter(typeof(SearchInfo), "x"); 参数表达式
2. Expression.Property(parameterExpression, (MethodInfo)MethodBase.GetMethodFromHandle(ldtoken(get_Name()))) 属性表达式
3. new Expression[] { Expression.Constant("5", typeof(string)) } 常数表达式
4. (MethodInfo)MethodBase.GetMethodFromHandle(ldtoken(Equals())) 方法调用表达式
5. Expression.Lambda<Func<SearchInfo, bool>>(Expression.Call( 2, 4, 3), 1); 创建Lambda表达式
接下来回到最开始的Lambda表达式, 图解说明以上的代码分别代表Lambda表达式的每个部分:
理解上表达式生成的5个步骤, 接下来还原一个表达式完整的创建过程, 如下:
//1.创建参数表达式
ParameterExpression parameterExpression = Expression.Parameter(typeof(SearchInfo), "x"); //2.创建属性表达式
Expression proerty = Expression.Property(parameterExpression, typeof(SearchInfo).GetProperty("Name")); //3.创建常数表达式
ConstantExpression constantExpression = Expression.Constant("", typeof(string)); //4.创建方法调用表达式
MethodCallExpression toString = Expression.Call(
proerty,
typeof(SearchInfo).GetMethod("Equals"),
new Expression[] { constantExpression }); //5.创建Lambda表达式
Expression<Func<SearchInfo, bool>> lambda = Expression.Lambda<Func<SearchInfo, bool>>(toString, new ParameterExpression[]
{
parameterExpression
});
以上则是如何创建一个表达式树, 测试调用, 如下:
bool res = lambda.Compile()(new SearchInfo() { Name = "" }); // “5”!=“55” 结果: false
注: Compile() 为lambda的编译, 后面则才能进行参数的传递
基于类(Class)动态生成表达式:
/// <summary>
/// 测试类
/// </summary>
public class SearchInfo
{
public string Name { get; set; } public string Code { get; set; } public string Id { get; set; } public string Addr { get; set; } public string Res { get; set; }
}
public static Func<T, bool> GenerateExpression<T>(T searchModel) where T : class, new()
{
List<MethodCallExpression> mcList = new List<MethodCallExpression>();
Type type = searchModel.GetType();
ParameterExpression parameterExpression = Expression.Parameter(type, "x");
var pros = type.GetProperties();
foreach (var t in pros)
{
var objValue = t.GetValue(searchModel, null);
if (objValue != null)
{
Expression proerty = Expression.Property(parameterExpression, t);
ConstantExpression constantExpression = Expression.Constant(objValue, t.PropertyType);
mcList.Add(Expression.Call(proerty, typeof(string).GetMethod("Contains"), new Expression[] { constantExpression }));
}
} if (mcList.Count == )
return Expression.Lambda<Func<T, bool>>(Expression.Constant(true, typeof(bool)), new ParameterExpression[] { parameterExpression }).Compile();
else
return Expression.Lambda<Func<T, bool>>(MethodCall(mcList), new ParameterExpression[] { parameterExpression }).Compile();
} public static Expression MethodCall<T>(List<T> mcList) where T : MethodCallExpression
{
if (mcList.Count == ) return mcList[];
BinaryExpression binaryExpression = null;
for (int i = ; i < mcList.Count; i += )
{
if (i < mcList.Count - )
{
BinaryExpression binary = Expression.OrElse(mcList[i], mcList[i + ]);
if (binaryExpression != null)
binaryExpression = Expression.OrElse(binaryExpression, binary);
else
binaryExpression = binary;
}
}
if (mcList.Count % != )
return Expression.OrElse(binaryExpression, mcList[mcList.Count - ]);
else
return binaryExpression;
}
测试代码 :
static void Main(string[] args)
{
var func = GenerateExpression(new SearchInfo()); List<SearchInfo> List = new List<SearchInfo>();
List.Add(new SearchInfo() { Code = "", Id = "", Name = "", Addr = "", Res = "" });
List.Add(new SearchInfo() { Code = "", Id = "", Name = "", Addr = "", Res = "" });
List.Add(new SearchInfo() { Code = "", Id = "", Name = "", Addr = "", Res = "" });
List.Add(new SearchInfo() { Code = "", Id = "", Name = "", Addr = "", Res = "" });
List.Add(new SearchInfo() { Code = "", Id = "", Name = "", Addr = "", Res = "" });
List.Add(new SearchInfo() { Code = "", Id = "", Name = "", Addr = "", Res = "" });
List.Add(new SearchInfo() { Code = "", Id = "", Name = "", Addr = "", Res = "" });
List.Add(new SearchInfo() { Code = "", Id = "", Name = "", Addr = "", Res = "" }); var ii = List.Where(func).ToList(); //8个结果
}
Expression表达式树(C#)的更多相关文章
- 介绍一个可以将Expression表达式树解析成Transact-SQL的项目Expression2Sql
一.Expression2Sql介绍 Expression2Sql是一个可以将Expression表达式树解析成Transact-SQL的项目.简单易用,几分钟即可上手使用,因为博主在设计Expres ...
- 委托、匿名委托、Lambda 表达式、Expression表达式树之刨根问底
本篇不是对标题所述之概念的入门文章,重点在阐述它们的异同点和应用场景.各位看官,这里就不啰嗦了,直接上代码. 首先定义一个泛型委托类型,如下: public delegate T Function&l ...
- .net 系列:Expression表达式树、lambda、匿名委托 的使用
首先定义一个泛型委托类型,如下: public delegate T Function<T>(T a, T b); 实现泛型委托的主体代码,并调用: public static strin ...
- .net 系列:Expression表达式树、lambda、匿名委托 的使用【转】
https://www.cnblogs.com/nicholashjh/p/7928205.html 首先定义一个泛型委托类型,如下: public delegate T Function<T& ...
- .NET技术-6.0. Expression 表达式树 生成 Lambda
.NET技术-6.0. Expression 表达式树 生成 Lambda public static event Func<Student, bool> myevent; public ...
- Expression表达式树
表达式树表示树状数据结构的代码,树状结构中的每个节点都是一个表达式,例如一个方法调用或类似 x < y 的二元运算 1.利用 Lambda 表达式创建表达式树 Expression<Fun ...
- 关于Expression表达式树的拼接
最近在做项目中遇到一个问题,需求是这样的: 我要对已经存在的用户进行检索,可以根据用户的id 或者用户名其中的一部分字符来检索出来,这样就出现了三种情况 只有id,只有用户名中一部字符,或者全部都有. ...
- Expression 表达式树学习整理
整理了一下表达式树的一些东西,入门足够了 先从ConstantExpression 开始一步一步的来吧 它表示具有常量值的表达式 我们选建一个控制台应用程序 ConstantExpression _ ...
- (转)Expression 表达式树学习整理
原文地址:http://www.cnblogs.com/li-peng/p/3154381.html 整理了一下表达式树的一些东西,入门足够了 先从ConstantExpression 开始一步一步的 ...
随机推荐
- R语言适配问题集锦
画图时的中文乱码问题 我这是Mac Yousemite 10.10.5,在两个地方遇到了中文乱码 1.使用wordcloud包绘制中文标签云时. library(wordcloud) mydata & ...
- new,malloc,GlobalAlloc具体解释
WINDOWS下最好的方式是用VirtualAlloc分配内存,他不是在堆,也不是栈,而是直接在进程的地址空间中保留一快内存.尽管用起来最不方便. 可是速度快,也最灵活 new,malloc,Glob ...
- SVN管理工具的使用(实习第9天)
最后就是我进行提交代码的时候要记得写注释,自己写了那些方法要标明,或者自己修改了哪些功能也要表明.不然我会被骂的. 2>代码冲突解决的问题: 服务器上的代码跟自己代码改动的地方不同 这种情况比较 ...
- Mvc前后端显示不同的404错误页
最近做的系统前端是移动端的,后端是PC端,然后404页面不能用通一个,so 查找了一些资料,找到了一个解决办法 在Global.asax文件夹下添加Application_EndRequest事件处 ...
- [JSOI2007]建筑抢修 优先队列 贪心
Code: #include<cstdio> #include<algorithm> #include<cstring> #include<queue> ...
- yii2.0中使用jquery
我们都知道 yii 框架是组件式开发的,使用 jquery 也是非常简单的.只需要注册一下就可以使用非常简单的 jquery 代码了! <?php $this->beginBlock('s ...
- 用JS中的cookie实现商品的浏览记录
最近在做一个购物车效果,为了实现商品的浏览记录效果可是让我百般周折,避免以后忘记特写此随笔与大家共享,希望博友们看后有所收获. 第一步:在一个公用的js文件下getCookie(“liulan”),c ...
- ArcGIS api for javascript——放大时切换图层
描述 本例展示了如何在地图里指出显示的缓存或切片的细节等级(LODs).当打开示例地图,可以看到一些来自ArcGIS Online ESRI_Imagery_World_2D图层的影像.这个应用程序配 ...
- Liquibase被锁
经常运行过程中出现 Liquibase - Waiting for changelog lock Waiting for changelog lock.... Running the migratio ...
- [Recompose] Pass a React Prop to a Stream in RxJS
When you declare your Component and Props in JSX, you can pass those props along to your RxJS stream ...