表达式树在C#中的作用
内容摘要
表达式树(Expression Tree)将代码逻辑表示为树状数据结构,而非直接编译为中间语言(IL)。其核心作用在于允许在运行时检查、修改、转换或编译执行代码逻辑。
主要应用场景:
- LINQ 提供程序转换:如 Entity Framework 将 C# Lambda 表达式解析并转换为 SQL 查询语句 。
- 动态代码生成与高性能反射替代:通过
Compile()将表达式树编译为委托,比传统反射(Reflection)性能高出一个数量级,常用于 ORM 映射、序列化框架及依赖注入容器 。 - 动态查询构建:在运行时根据用户输入动态拼接查询条件 。
- 规则引擎:将业务规则存储为表达式树,实现灵活的计算逻辑 。
代码演示
通过下面实例,更加了解其作用
using System;
using System.Linq.Expressions;
using System.Reflection;
public class ExpressionTreeDemo
{
public static void Main()
{
// 场景1: 动态构建并编译执行代码 (例如: (a, b) => a + b)
var paramA = Expression.Parameter(typeof(int), "a");
var paramB = Expression.Parameter(typeof(int), "b");
var addBody = Expression.Add(paramA, paramB);
var lambda = Expression.Lambda<Func<int, int, int>>(addBody, paramA, paramB);
// 编译为可执行委托
Func<int, int, int> addFunc = lambda.Compile();
Console.WriteLine($"动态计算结果: {addFunc(3, 5)}"); // 输出: 8
// 场景2: 替代反射实现高性能属性访问
var person = new Person { Name = "Alice" };
// 创建动态 Getter: p => p.Name
var getter = CreateGetter<Person, string>("Name");
Console.WriteLine($"动态获取属性: {getter(person)}"); // 输出: Alice
// 创建动态 Setter: (p, val) => p.Name = val
var setter = CreateSetter<Person, string>("Name");
setter(person, "Bob");
Console.WriteLine($"动态设置后属性: {person.Name}"); // 输出: Bob
}
// 动态生成属性 Getter 委托
static Func<T, TProperty> CreateGetter<T, TProperty>(string propertyName)
{
var param = Expression.Parameter(typeof(T), "x");
var property = Expression.Property(param, propertyName);
var lambda = Expression.Lambda<Func<T, TProperty>>(property, param);
return lambda.Compile();
}
// 动态生成属性 Setter 委托
static Action<T, TProperty> CreateSetter<T, TProperty>(string propertyName)
{
var objParam = Expression.Parameter(typeof(T), "x");
var valueParam = Expression.Parameter(typeof(TProperty), "value");
var property = Expression.Property(objParam, propertyName);
var assign = Expression.Assign(property, valueParam);
var lambda = Expression.Lambda<Action<T, TProperty>>(assign, objParam, valueParam);
return lambda.Compile();
}
}
public class Person
{
public string Name { get; set; }
}