技术
Expression的用法
田敏
2024-12-052 分钟阅读.NETC#Backend
Expression 和 IQueryable 是 .NET 中非常重要的特性,特别是在处理动态 LINQ 查询、延迟执行等场景时。以下是它们的详细解析与用法。
1. Expression 的用法
1.1 概述
Expression是一个表达式树,可以用来描述代码(比如 lambda 表达式)结构,而不实际执行代码。- 它常用在动态 LINQ 查询、构建动态条件等场景中。
核心类:
Expression<TDelegate>:表示具有强类型的表达式树。- 常用
Func<T, TResult>或Action<T>作为泛型参数。
1.2 用法示例
1.2.1 动态构建表达式树
用来动态生成查询条件。
using System;
using System.Linq.Expressions;
class Program
{
static void Main()
{
// 定义一个参数 x
ParameterExpression param = Expression.Parameter(typeof(int), "x");
// 定义表达式 x > 5
Expression body = Expression.GreaterThan(param, Expression.Constant(5));
// 构建 Lambda 表达式 x => x > 5
Expression<Func<int, bool>> lambda = Expression.Lambda<Func<int, bool>>(body, param);
// 测试表达式
Func<int, bool> compiledLambda = lambda.Compile();
Console.WriteLine(compiledLambda(10)); // 输出 True
}
}
1.2.2 动态 LINQ 查询
动态条件构建。
using System;
using System.Linq;
using System.Linq.Expressions;
using System.Collections.Generic;
class Program
{
static void Main()
{
var data = new List<int> { 1, 2, 3, 4, 5, 6, 7 };
// 动态创建查询条件 x => x > 3
ParameterExpression param = Expression.Parameter(typeof(int), "x");
Expression body = Expression.GreaterThan(param, Expression.Constant(3));
Expression<Func<int, bool>> predicate = Expression.Lambda<Func<int, bool>>(body, param);
// 使用条件过滤数据
var result = data.AsQueryable().Where(predicate);
Console.WriteLine(string.Join(", ", result)); // 输出 4, 5, 6, 7
}
}
1.2.3 常见操作符
Expression.Add:加法。Expression.AndAlso:逻辑与。Expression.Equal:相等。Expression.Call:方法调用。
动态生成表达式:
Expression<Func<int, int, int>> addExpression =
Expression.Lambda<Func<int, int, int>>(
Expression.Add(
Expression.Parameter(typeof(int), "a"),
Expression.Parameter(typeof(int), "b")
),
Expression.Parameter(typeof(int), "a"),
Expression.Parameter(typeof(int), "b")
);
2. IQueryable 的用法
2.1 概述
IQueryable<T>是一个接口,继承自IEnumerable<T>。- 它支持 延迟执行 和 表达式树解析。
- 常见的场景是和 ORM(如 Entity Framework)一起使用。
关键点:
- 延迟执行:只有当调用
ToList、Count、First等终结方法时,查询才会被执行。 - 表达式树:查询会被解析成表达式树并翻译为数据库查询。
2.2 用法示例
2.2.1 基本查询
using System.Linq;
var numbers = Enumerable.Range(1, 10).AsQueryable();
// 查询大于 5 的数字
var query = numbers.Where(x => x > 5);
// 查询未执行(延迟执行)
Console.WriteLine("Query defined");
// 查询执行
var result = query.ToList();
Console.WriteLine(string.Join(", ", result)); // 输出 6, 7, 8, 9, 10
2.2.2 使用自定义表达式
using System;
using System.Linq;
using System.Linq.Expressions;
class Program
{
static void Main()
{
var numbers = Enumerable.Range(1, 10).AsQueryable();
// 动态生成表达式 x => x > 5
ParameterExpression param = Expression.Parameter(typeof(int), "x");
Expression body = Expression.GreaterThan(param, Expression.Constant(5));
Expression<Func<int, bool>> predicate = Expression.Lambda<Func<int, bool>>(body, param);
// 使用动态表达式查询
var result = numbers.Where(predicate).ToList();
Console.WriteLine(string.Join(", ", result)); // 输出 6, 7, 8, 9, 10
}
}
2.2.3 常见扩展方法
- 过滤:
Where - 投影:
Select - 排序:
OrderBy,OrderByDescending - 聚合:
Sum,Count,Max,Min
3. 两者结合的使用
利用 Expression 和 IQueryable 实现复杂动态查询。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
class Program
{
static void Main()
{
var data = new List<User>
{
new User { Id = 1, Name = "Alice", Age = 25 },
new User { Id = 2, Name = "Bob", Age = 30 },
new User { Id = 3, Name = "Charlie", Age = 35 }
}.AsQueryable();
// 动态生成条件 x => x.Age > 30
ParameterExpression param = Expression.Parameter(typeof(User), "x");
Expression body = Expression.GreaterThan(
Expression.Property(param, "Age"),
Expression.Constant(30)
);
Expression<Func<User, bool>> predicate = Expression.Lambda<Func<User, bool>>(body, param);
// 使用动态条件查询
var result = data.Where(predicate).ToList();
result.ForEach(x => Console.WriteLine(x.Name)); // 输出 Charlie
}
class User
{
public int Id { get; set; }
public string Name { get; set; }
public int Age { get; set; }
}
}
4. 总结
| 特性 | Expression | IQueryable |
| ---------------- | ---------------------------------------- | ------------------------------------------ |
| 作用 | 表达代码的结构(动态生成和解析表达式树) | 表示可查询的数据源,支持延迟执行和表达式树 |
| 主要应用场景 | 动态查询、规则引擎、代码生成 | 数据库查询、LINQ 操作 |
| 是否延迟执行 | 不涉及执行 | 支持延迟执行 |
| 扩展性 | 用于生成复杂的动态条件 | 可结合 Expression 动态构建查询 |
两者结合,可以实现高效、灵活的查询处理。
版权协议:MIT返回列表