动态创建 Lambda 表达式

时间:2022-02-21 19:04:10

首先我们看一个简单 Lambda 表达式的构成。

i => i > 5


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

例子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。

例子3

var ints = new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
// var r = ints.Where(i => (i > 5 && i <= 7) || (i == 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());

例子4

var ints = new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
//var r = ints.Select(i => i % 2 == 0 ? i : 0); // 要实现的表达式

// 创建参数 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());

例子5

var ints = new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
// Array.ForEach<int>(ints, i => Console.WriteLine(i)); // 要实现的表达式

// 创建参数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());