【Expression笔记】基础
简介
表达式树(Expression Tree):树形数据结构表示代码,以表示逻辑运算,以便可以在运行时访问逻辑运算的结构。
使用Expression<TDelegate>
类型来表示表达式树
Expression
对象储存了运算逻辑,它把运算逻辑保存成抽象语法树(AST),可以在运行时动态获取运算逻辑。而普通委托则没有。
使用场景
- 根据表达式树生成sql
b.Name.Contains('范') -> where Name like '%范%'
- 动态修改表达式树
如何查看表达式树
- 方法1、安装VS插件ExpressionTreeVisualizer(安装麻烦)
https://github.com/zspitz/ExpressionTreeVisualizer/releases
- 方法2、安装Nuget:
Install-Package ExpressionTreeToString
using System.Linq.Expressions;
using ExpressionTreeToString;
Expression<Func<Book, bool>> exp1 = b => b.Price > 5M;
Console.WriteLine(exp1.ToString("Object notation", "C#"));
输出:
var b = new ParameterExpression {
Type = typeof(Book),
IsByRef = false,
Name = "b"
};
new Expression<Func<Book, bool>> {
NodeType = ExpressionType.Lambda,
Type = typeof(Func<Book, bool>),
Parameters = new ReadOnlyCollection<ParameterExpression> {
b
},
Body = new BinaryExpression {
NodeType = ExpressionType.GreaterThan,
Type = typeof(bool),
Left = new MemberExpression {
Type = typeof(decimal),
Expression = b,
Member = typeof(Book).GetProperty("Price")
},
Right = new ConstantExpression {
Type = typeof(decimal),
Value = 5
},
Method = typeof(decimal).GetMethod("op_GreaterThan")
},
ReturnType = typeof(bool)
}
动态创建表达式树
参考上面的输出内容,我们可以写代码动态构建表达式树,如下:
var b = Expression.Parameter(typeof(Book), "b");
var left = Expression.MakeMemberAccess(b, typeof(Book).GetProperty("Price"));
var right = Expression.Constant(5M, typeof(decimal));
var body = Expression.MakeBinary(ExpressionType.GreaterThan, left, right, false, typeof(decimal).GetMethod("op_GreaterThan"));
Expression<Func<Book, bool>> exp2 = (Expression<Func<Book, bool>>)Expression.Lambda(body, b);
//测试
bool result = exp2.Compile().Invoke(new Book { Price = 10M });//true
更简单的方法构建表达式树
修改ToString参数Object notation
-> Factory methods
,可以直接生成构建代码:
Console.WriteLine(exp1.ToString("Factory methods", "C#"));
输出:
using static System.Linq.Expressions.Expression
var b = Parameter(
typeof(Book),
"b"
);
Lambda(
MakeBinary(ExpressionType.GreaterThan,
MakeMemberAccess(b,
typeof(Book).GetProperty("Price")
),
Constant(5), false,
typeof(decimal).GetMethod("op_GreaterThan")
),
b
);
从Lambda表达式生成表达式树
Expression<Func<Book, bool>> e1 = b =>b.Price > 5;