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");
 
bool res = lambda.Compile()(new SearchInfo() { Name = "6" }); // 结果 : false

注释: 为了能够了解 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#)的更多相关文章

  1. 介绍一个可以将Expression表达式树解析成Transact-SQL的项目Expression2Sql

    一.Expression2Sql介绍 Expression2Sql是一个可以将Expression表达式树解析成Transact-SQL的项目.简单易用,几分钟即可上手使用,因为博主在设计Expres ...

  2. 委托、匿名委托、Lambda 表达式、Expression表达式树之刨根问底

    本篇不是对标题所述之概念的入门文章,重点在阐述它们的异同点和应用场景.各位看官,这里就不啰嗦了,直接上代码. 首先定义一个泛型委托类型,如下: public delegate T Function&l ...

  3. .net 系列:Expression表达式树、lambda、匿名委托 的使用

    首先定义一个泛型委托类型,如下: public delegate T Function<T>(T a, T b); 实现泛型委托的主体代码,并调用: public static strin ...

  4. .net 系列:Expression表达式树、lambda、匿名委托 的使用【转】

    https://www.cnblogs.com/nicholashjh/p/7928205.html 首先定义一个泛型委托类型,如下: public delegate T Function<T& ...

  5. .NET技术-6.0. Expression 表达式树 生成 Lambda

    .NET技术-6.0. Expression 表达式树 生成 Lambda public static event Func<Student, bool> myevent; public ...

  6. Expression表达式树

    表达式树表示树状数据结构的代码,树状结构中的每个节点都是一个表达式,例如一个方法调用或类似 x < y 的二元运算 1.利用 Lambda 表达式创建表达式树 Expression<Fun ...

  7. 关于Expression表达式树的拼接

    最近在做项目中遇到一个问题,需求是这样的: 我要对已经存在的用户进行检索,可以根据用户的id 或者用户名其中的一部分字符来检索出来,这样就出现了三种情况 只有id,只有用户名中一部字符,或者全部都有. ...

  8. Expression 表达式树学习整理

    整理了一下表达式树的一些东西,入门足够了 先从ConstantExpression 开始一步一步的来吧  它表示具有常量值的表达式 我们选建一个控制台应用程序 ConstantExpression _ ...

  9. (转)Expression 表达式树学习整理

    原文地址:http://www.cnblogs.com/li-peng/p/3154381.html 整理了一下表达式树的一些东西,入门足够了 先从ConstantExpression 开始一步一步的 ...

随机推荐

  1. less09 判断语句

    less //.mixin (@a) when (lightness(@a) >= 50%) { //255/2=127.5 // background-color: black; //} // ...

  2. hdoj--1408--盐水的故事(技巧)

    盐水的故事 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Subm ...

  3. MinGW安装和使用基础教程

    MinGW全称Minimalist GNU For Windows,是个精简的Windows平台C/C++.ADA及Fortran编译器,相比Cygwin而言,体积要小很多,使用较为方便.MinGW提 ...

  4. Find and counter

    Find: In a sense, find is the opposite of the [] operator. Instead of taking an index and extracting ...

  5. Vue简单用法目录总结 以及 前端基础总结传送门:

    Vue官方网址:https://cn.vuejs.org/ Vue 第三方组件:Element:http://element-cn.eleme.io/#/zh-CN Vue 基础指令以及自定义指令:h ...

  6. <Sicily>Polynomial

    一.题目描述 Given a polynomial and the value of the variable x, you task is to calculate the value of the ...

  7. 添加本地 yum源

    添加本地 yum源 yum-updatesd.conf yum的主配置文件   [root@zhou ~]# cd /etc/yum.repos.d/ [root@zhou yum.repos.d]# ...

  8. JTable表格案例

    package com.szht.gpy.frame; import java.awt.BorderLayout; import java.awt.event.ActionEvent; import ...

  9. sys.path

    sys.path.append() 和 sys.path.insert() python程序中使用 import XXX 时,python解析器会在当前目录.已安装和第三方模块中搜索 xxx,如果都搜 ...

  10. 钓鱼WIFI的防范

    实际上,Wi-Fi接入点(AP).路由器和热点常常是高度暴露的攻击面.用户一不小心就有可能踏进攻击者设置的Wi-Fi陷阱,为企业造成信息泄露或经济损失. 如今Wi-Fi 6时代悄然到来,为高密海量无线 ...