详解C# Lambda表达式的动态生成(1)
对于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 };
- //var r = ints.Where(i => i > 5);
- // 要实现的表达式
- // 创建参数 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());
在代码中设置断点,我们可以看到调试器中显示的表达式信息。
图1
.NET FX 3.5 中为 Lambda 新增了一些委托类型。
(1) 用于处理无返回数据的 Action。
- public delegate void
- Action()
- public delegate void
- Action<T> (T arg)
- public delegate void
- Action<T1, T2> (T1 arg1, T2 arg2)
- public delegate void
- Action<T1, T2, T3>
- (T1 arg1, T2 arg2, T3 arg3)
- public delegate void
- Action<T1, T2, T3, T4>
- (T1 arg1, T2 arg2, T3 arg3, T4 arg4)
(2) 用于处理带返回数据的 Func。
- public delegate TResult
- Func<TResult> ()
- public delegate TResult
- Func<T, TResult> (T arg)
- public delegate TResult
- Func<T1, T2, TResult>
- (T1 arg1, T2 arg2)
- public delegate TResult
- Func<T1, T2, T3, TResult>
- (T1 arg1, T2 arg2, T3 arg3)
- public delegate TResult
- Func<T1, T2, T3, T4, TResult>
- (T1 arg1, T2 arg2, T3 arg3, T4 arg4)
我们还可以进行更复杂的组合。
动态构建C# Lambda表达式例子2
- var ints =
- new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
- // var r =
- ints.Where(i => i > 5 && i <= 7);
- // 要实现的表达式
- // 创建参数 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());
在例子2中,我们对复杂的表达式进行了分解,并使用 And 完成多个表达式的组装,由此我们可以创建更加复杂的逻辑组合,比如例子3。
共2页: 1 [2] 下一页 | |||
|
- 上一篇:数据库中LINQ执行存储过程的调用
- 下一篇:XML节点学习总结