详解C# Lambda表达式的动态生成

开发 后端
C# Lambda表达式的概念大家一定已经清楚了,那么如何动态生成C# Lambda表达式呢?具体的操作是什么呢?有什么需要注意的呢?那么本文就向你介绍具体的内容。

对于C# Lambda的理解我们在之前的文章中已经讲述过了,那么作为Delegate的进化使用,为了让代码简洁和优雅的呈现,C# Lambda表达式的使用功不可灭,那么依托外部条件如何动态构建C# Lambda表达式呢。下面让我们来具体的看看实施。

或许你会奇怪这个需求是如何产生的…… 首先,Lambda 在 DLinq 中承担了以往 T-SQL 的部分角色;其次,在数据库设计中,我们往往需要依据外部未知的动态条件组合来查询数据。而问题在于作为一种静态语言,我们显然无法用动态语法或者拼接字符串的方法来创建一个Delegate/Lambda,那么如何达到类似的目的呢?CodeDom?Emit?或许最佳的选择是 System.Linq.Expressions.Expression。

1、首先我们了解一个简单C# Lambda表达式的构成。

  1. i => i > 5 

在这个表达式中,"i" 被称为 Parameter,"i > 5" 是 Body。我们可以对 Body 进行更进一步的分解,那么 "i > 5" 分别包含参数(i)、操作符(>)以及一个常数(5)。所有这些通过特定顺序的组合,从而构建一个完整的 Lambda 表达式。

2、我们通过一些例子,来学习如何动态构建C# Lambda表达式

动态构建C# Lambda表达式例子1

  1. var ints =   
  2. new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 };  
  3. //var r = ints.Where(i => i > 5);   
  4. // 要实现的表达式  
  5.  
  6. // 创建参数 i  
  7. var parameter =   
  8. Expression.Parameter(typeof(int), "i");  
  9.  
  10. // 创建常量5  
  11. var constant =   
  12. Expression.Constant(5);  
  13.  
  14. // 创建比较表达式 i > 5  
  15. var bin =   
  16. Expression.GreaterThan(parameter, constant);  
  17.  
  18. // 获取Lambda表达式  
  19. var lambda =   
  20. Expression.Lambda<Func<intbool>>(bin, parameter);  
  21.  
  22. // 通过 Compile 方法获取 Delegate  
  23. var _r = ints.Where(lambda.Compile());  

在代码中设置断点,我们可以看到调试器中显示的表达式信息。

图1

.NET FX 3.5 中为 Lambda 新增了一些委托类型。

(1) 用于处理无返回数据的 Action。

  1. public delegate void   
  2. Action()  
  3. public delegate void   
  4. Action<T> (T arg)  
  5. public delegate void   
  6. Action<T1, T2> (T1 arg1, T2 arg2)  
  7. public delegate void   
  8. Action<T1, T2, T3>   
  9. (T1 arg1, T2 arg2, T3 arg3)  
  10. public delegate void   
  11. Action<T1, T2, T3, T4>   
  12. (T1 arg1, T2 arg2, T3 arg3, T4 arg4) 

(2) 用于处理带返回数据的 Func。

  1. public delegate TResult   
  2. Func<TResult> ()  
  3. public delegate TResult  
  4. Func<T, TResult> (T arg)  
  5. public delegate TResult   
  6. Func<T1, T2, TResult>   
  7. (T1 arg1, T2 arg2)  
  8. public delegate TResult   
  9. Func<T1, T2, T3, TResult>   
  10. (T1 arg1, T2 arg2, T3 arg3)  
  11. public delegate TResult   
  12. Func<T1, T2, T3, T4, TResult>   
  13. (T1 arg1, T2 arg2, T3 arg3, T4 arg4) 

我们还可以进行更复杂的组合。

动态构建C# Lambda表达式例子2

  1. var ints =   
  2. new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 };  
  3. // var r =   
  4. ints.Where(i => i > 5 && i <= 7);  
  5.  // 要实现的表达式  
  6.  
  7. // 创建参数 i  
  8. var parameter =   
  9. Expression.Parameter(typeof(int), "i");  
  10.  
  11. // 创建表达式 i > 5   
  12. var con1 =   
  13. Expression.Constant(5);  
  14. var bin1 =   
  15. Expression.GreaterThan(parameter, con1);  
  16.  
  17. // 创建表达式 i <= 7  
  18. var con2 =   
  19. Expression.Constant(7);  
  20. var bin2 =   
  21. Expression.LessThanOrEqual(parameter, con2);  
  22.  
  23. // 组合两个表达式  
  24. var body =   
  25. Expression.And(bin1, bin2);  
  26.  
  27. // 获取 Lambda 表达式  
  28. var lambda =   
  29. Expression.Lambda<Func<intbool>>(body, parameter);  
  30.  
  31. var _r = ints.Where(lambda.Compile());  

在例子2中,我们对复杂的表达式进行了分解,并使用 And 完成多个表达式的组装,由此我们可以创建更加复杂的逻辑组合,比如例子3。#p#

动态构建C# Lambda表达式例子3

  1. var ints =   
  2. new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 };  
  3. // var r =   
  4. ints.Where(i => (i > 5 && i <= 7) || (i == 3));   
  5. // 要实现的表达式  
  6.  
  7. // 创建参数 i  
  8. var parameter =   
  9. Expression.Parameter(typeof(int), "i");  
  10.  
  11. // 创建表达式 i > 5  
  12. var con1 =   
  13. Expression.Constant(5);  
  14. var bin1 =   
  15. Expression.GreaterThan(parameter, con1);  
  16.  
  17. // 创建表达式 i < 7  
  18. var con2 =   
  19. Expression.Constant(7);  
  20. var bin2 =   
  21. Expression.LessThanOrEqual(parameter, con2);  
  22.  
  23. // 创建表达式 i == 3  
  24. var con3 =   
  25. Expression.Constant(3);  
  26. var bin3 =   
  27. Expression.Equal(parameter, con3);  
  28.  
  29. // 组合 i > 5 && i <= 7  
  30. var body =   
  31. Expression.And(bin1, bin2);  
  32.  
  33. // 组合 ( i > 5 && i <= 7) OR (i == 3)  
  34. body = Expression.Or(body, bin3);  
  35.  
  36. var lambda =   
  37. Expression.Lambda<Func<intbool>>  
  38. (body, parameter);  
  39. var _r = ints.Where(lambda.Compile());  

我们继续看几个常见的例子。

动态构建C# Lambda表达式例子4

  1. var ints =   
  2. new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 };  
  3. //var r = ints.Select(i => i % 2 == 0 ? i : 0);   
  4. // 要实现的表达式  
  5.  
  6. // 创建参数 i  
  7. var parameter =   
  8. Expression.Parameter(typeof(int), "i");  
  9.  
  10. // 创建表达式 i % 2  
  11. var con1 =   
  12. Expression.Constant(2);  
  13. var bin1 =   
  14. Expression.Modulo(parameter, con1);  
  15.  
  16. // 创建表达式 (i % 2) == 0  
  17. var con2 =   
  18. Expression.Constant(0);  
  19. var bin2 =   
  20. Expression.Equal(bin1, con2);  
  21.  
  22. // 创建表达式 IIF(((i % 2) = 0), i, 0)  
  23. var bin3 =   
  24. Expression.Condition  
  25. (bin2, parameter, Expression.Constant(0));  
  26.  
  27. var lambda =   
  28. Expression.Lambda<Func<intint>>(bin3, parameter);  
  29. var _r = ints.Select(lambda.Compile());  

动态构建C# Lambda表达式例子5

  1. var ints =   
  2. new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 };  
  3. // Array.ForEach<int>(ints, i => Console.WriteLine(i));  
  4.  // 要实现的表达式  
  5.  
  6. // 创建参数i  
  7. var parameter =   
  8. Expression.Parameter(typeof(int), "i");  
  9.  
  10. // 获取 Console.WriteLine MethodInfo  
  11. MethodInfo method =   
  12. typeof(Console).GetMethod(  
  13. "WriteLine"new Type[] { typeof(int) });  
  14.  
  15. // 创建表达式   
  16. var call = Expression.Call(method, parameter);  
  17.  
  18. var lambda =   
  19. Expression.Lambda<Action<int>>(call, parameter);  
  20. Array.ForEach<int>(  
  21. ints, lambda.Compile());  

是该花点时间去好好研究一下 System.Linq.Expressions Namespace 了……

动态构建C# Lambda表达式的基本内容就向你介绍到这里,希望那个对你了解和掌握使用动态构建C# Lambda表达式有所帮助。

【编辑推荐】

  1. LINQ to SQL删除实现体会小结
  2. LINQ删除记录的操作实现
  3. 实现LINQ删除数据的巧妙方法
  4. 详解实现LINQ to SQL删除行
  5. C# Lambda Expression概念浅析
责任编辑:仲衡 来源: rainsts.net
相关推荐

2009-08-27 09:44:59

C# Lambda表达

2010-09-14 14:05:42

C#委托

2009-07-09 09:51:07

Lambda表达式C#

2009-08-26 16:17:23

C# Lambda表达

2009-08-27 09:57:50

C# Lambda表达

2024-03-25 13:46:12

C#Lambda编程

2009-08-07 15:41:39

C#正规表达式

2021-08-31 07:19:41

Lambda表达式C#

2009-07-01 09:56:10

C#3.0

2022-01-14 07:56:39

C#动态查询

2022-11-07 07:11:19

C#lambda函数

2011-05-20 17:50:45

C#

2010-10-19 10:03:02

Lambda表达式

2009-08-03 17:27:14

C#正则表达式

2020-10-16 06:40:25

C++匿名函数

2009-04-09 09:19:25

C#规则表达式.NET

2009-08-20 16:23:32

C#正则表达式语法

2022-09-19 14:12:27

C++Lambda表达式

2023-11-02 08:25:58

C++Lambda

2022-12-05 09:31:51

接口lambda表达式
点赞
收藏

51CTO技术栈公众号