动态生成C# Lambda表达式
转载:http://www.educity.cn/develop/1407905.html,并整理!
对于C# Lambda的理解我们在之前的文章中已经讲述过了,那么作为Delegate的进化使用,为了让代码简洁和优雅的呈现,C# Lambda表达式的使用功不可灭,那么依托外部条件如何动态构建C# Lambda表达式呢。下面让我们来具体的看看实施。
或许你会奇怪这个需求是如何产生的…… 首先,Lambda 在 DLinq 中承担了以往 T-SQL 的部分角色;其次,在数据库设计中,我们往往需要依据外部未知的动态条件组合来查询数据。而问题在于作为一种静态语言,我们显然无法用动态语法或者拼接字符串的方法来创建一个Delegate/Lambda,那么如何达到类似的目的呢?CodeDom?Emit?或许最佳的选择是 System.Linq.Expressions.Expression。
1、首先我们了解一个简单C# Lambda表达式的构成。
i => i > 5
在这个表达式中,"i" 被称为 Parameter,"i > 5" 是 Body。我们可以对 Body 进行更进一步的分解,那么 "i > 5" 分别包含参数(i)、操作符(>)以及一个常数(5)。所有这些通过特定顺序的组合,从而构建一个完整的 Lambda 表达式。
2、我们通过一些例子,来学习如何动态构建C# Lambda表达式。
动态构建C# Lambda表达式例子①
1、准备例子
var ints = new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
2、要实现的表达式
var r = ints.Where(i => i > 5);
3、动态创建该表达式具体代码
// 创建参数 i var parameter = Expression.Parameter(typeof(int), "i"); // 创建常量5 var constant = Expression.Constant(5); // 创建比较表达式 i > 5 var bin = Expression.GreaterThan(parameter, constant); // 获取Lambda表达式 var lambda = Expression.Lambda<Func<int, bool>>(bin, parameter); // 通过 Compile 方法获取 Delegate var _r = ints.Where(lambda.Compile());
动态构建C# Lambda表达式例子②
1、准备例子
var ints = new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
2、要实现的表达式
var r = ints.Where(i => i > 5 && i <= 7);
3、动态创建该表达式具体代码
// 创建参数 i var parameter = Expression.Parameter(typeof(int), "i"); // 创建表达式 i > 5 var con1 = Expression.Constant(5); var bin1 = Expression.GreaterThan(parameter, con1); // 创建表达式 i <= 7 var con2 = Expression.Constant(7); var bin2 = Expression.LessThanOrEqual(parameter, con2); // 组合两个表达式 var body = Expression.And(bin1, bin2); // 获取 Lambda 表达式 var lambda = Expression.Lambda<Func<int, bool>>(body, parameter); var _r = ints.Where(lambda.Compile());
在例子②中,我们对复杂的表达式进行了分解,并使用 And 完成多个表达式的组装,由此我们可以创建更加复杂的逻辑组合,比如例子③。
动态构建C# Lambda表达式例子③
1、准备例子
var ints = new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
2、要实现的表达式
var r = ints.Where(i => (i > 5 && i <= 7) || (i == 3));
3、动态创建该表达式具体代码
// 创建参数 i var parameter = Expression.Parameter(typeof(int), "i"); // 创建表达式 i > 5 var con1 = Expression.Constant(5); var bin1 = Expression.GreaterThan(parameter, con1); // 创建表达式 i < 7 var con2 = Expression.Constant(7); var bin2 = Expression.LessThanOrEqual(parameter, con2); // 创建表达式 i == 3 var con3 = Expression.Constant(3); var bin3 = Expression.Equal(parameter, con3); // 组合 i > 5 && i <= 7 var body = Expression.And(bin1, bin2); // 组合 ( i > 5 && i <= 7) OR (i == 3) body = Expression.Or(body, bin3); var lambda = Expression.Lambda<Func<int, bool>> (body, parameter); var _r = ints.Where(lambda.Compile());
动态构建C# Lambda表达式例子④
1、准备例子
var ints = new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
2、要实现的表达式
var r = ints.Select(i => i % 2 == 0 ? i : 0);
3、动态创建该表达式具体代码
// 创建参数 i var parameter = Expression.Parameter(typeof(int), "i"); // 创建表达式 i % 2 var con1 = Expression.Constant(2); var bin1 = Expression.Modulo(parameter, con1); // 创建表达式 (i % 2) == 0 var con2 = Expression.Constant(0); var bin2 = Expression.Equal(bin1, con2); // 创建表达式 IIF(((i % 2) = 0), i, 0) var bin3 = Expression.Condition (bin2, parameter, Expression.Constant(0)); var lambda = Expression.Lambda<Func<int, int>>(bin3, parameter); var _r = ints.Select(lambda.Compile());
动态构建C# Lambda表达式例子⑤
1、准备例子
var ints = new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
2、要实现的表达式
Array.ForEach<int>(ints, i => Console.WriteLine(i));
3、动态创建该表达式具体代码
// 创建参数i var parameter = Expression.Parameter(typeof(int), "i"); // 获取 Console.WriteLine MethodInfo MethodInfo method = typeof(Console).GetMethod( "WriteLine", new Type[] { typeof(int) }); // 创建表达式 var call = Expression.Call(method, parameter); var lambda = Expression.Lambda<Action<int>>(call, parameter); Array.ForEach<int>( ints, lambda.Compile());
是该花点时间去好好研究一下 System.Linq.Expressions Namespace 了……
动态构建C# Lambda表达式的基本内容就向你介绍到这里,希望那个对你了解和掌握使用动态构建C# Lambda表达式有所帮助。