C#表达式树Expression基础讲解
什么是表达式树
表达式树以树形数据结构表示代码,其中每一个节点都是一种表达式,比如方法调用和 x < y 这样的二元运算等。可以对表达式树中的代码进行编辑和运算。 这样能够动态修改可执行代码、在不同数据库中执行 LINQ 查询以及创建动态查询。 表达式树还能用于动态语言运行时 (DLR) 以提供动态语言和 .NET 之间的互操作性,同时保证编译器编写员能够发射表达式树而非 Microsoft 中间语言 (MSIL)。 这段话是来自官网( [表达式树 (C#) | Microsoft Docs](表达式树 (C#) | Microsoft Docs) )的定义。
在 C# 中,我们可以通过 Expression 的方式来手动创建表达式树,比如:
[HttpGet]public IActionResult Expression(){// 查询 年龄Age 大于 18 的元素Expression> expression1 = x => x.Age > 18; return Ok(); }
那么,x.Age > 18 这一表达式,它的树状结构是这样的:
文章图片
通过 Visual Studio 自带的查看变量或添加监视的方式,我们可以发现其中 树的根节点(NodeType)是 GreaterThan,左节点(Left)是 x.Age,右节点(Right)是 18。所以由此就可以大概画出树状结构。
【C#表达式树Expression基础讲解】
文章图片
最后,通过这种树状结构,C# 就可以帮我们将表达式编译成具体的 SQL 执行语句。
如果想更清晰的查看表达式树的结构,可以 nuget 一个包( ExpressionTreeToString ),将表达式结构转换成字符串
PM> Install-Package ZSpitz.Util -Version 0.1.116
Expression> expression = u => u.Age >= 18; var treeStr = expression.ToString("Object notation", "C#"); // 输出为下面字符串var u = new ParameterExpression {Type = typeof(User),IsByRef = false,Name = "u"}; new Expression > {NodeType = ExpressionType.Lambda,Type = typeof(Func ),Parameters = new ReadOnlyCollection {u},Body = new BinaryExpression {NodeType = ExpressionType.GreaterThanOrEqual,Type = typeof(bool),Left = new MemberExpression {Type = typeof(int),Expression = u,Member = typeof(User).GetProperty("Age")},Right = new ConstantExpression {Type = typeof(int),Value = https://www.it610.com/article/18}},ReturnType = typeof(bool)}
Expression 和 Func 的区别
- Expression 存储了运算逻辑,可以将其保存成抽象语法树(AST),可以在运行时动态获取运算逻辑。
- Func 只是存储了结果,无法保存成语法树,也无法动态获取运算逻辑。
简单来说就是,此时要筛选 User 表中年龄大于18的数据,可以有这两种写法
// 这种写法,实际生成的 SQL 语句, 大概是这样的 SELECT * FROM User as T WHERE T.age > 18Expression> expression1 = x => x.Age > 18; dbContext.User.Where(expression1).toList(); // 而这种, 生成的语句是这样的 SELECT * FROM User, 然后将 User 表中所有数据加载到内存中后, 在进行 age > 18 的过滤Func func1 = x => x.Age > 18; dbContext.User.Where(func1).toList();
通过代码创建表达式树
- ParameterExpression
- BinaryExpression
- MethodCallExpression
- ConstantExpression
动态将表达式:u => u.Age >= 18; 通过代码构建出来一般构建步骤:
- 先创建 ParameterExpression
- 接着由里到外逐步构建
- 先左节点(Left)
- 后右节点(Right)
- 接着Body节点
- 将其拼接成 Expression
public IActionResult GetUserByManualExpression(){ParameterExpression parameterExpression = Expression.Parameter(type:typeof(User), name: "u"); ConstantExpression right = Expression.Constant(18); MemberExpression left = Expression.MakeMemberAccess(parameterExpression, member: typeof(User).GetProperty("Age")); BinaryExpression body = Expression.GreaterThanOrEqual(left, right); Expression> expression = Expression.Lambda >(body, parameters: parameterExpression); var data = https://www.it610.com/article/_userService.GetUsers(expression); return Ok(new{code = 200,msg ="OK",data}); }
到此这篇关于C#表达式树Expression基础讲解的文章就介绍到这了。希望对大家的学习有所帮助,也希望大家多多支持脚本之家。
推荐阅读
- 【生信技能树】R语言练习题|【生信技能树】R语言练习题 - 中级
- java中如何实现重建二叉树
- Python爬虫|Python爬虫 --- 1.4 正则表达式(re库)
- 种树郭橐驼传(文言句式+古今异义+词类活用+通假字)
- 白杨树
- 08黑龙江迟淑荣弯柳树网络学院第五期学习赵宗瑞老师主讲的(传统文化与身心健康)教育体系心得体会
- [原创]能见沂山一棵树,胜读十年无用书!
- 涵养字外功
- 2018.07.07《刺杀骑士团长》村上春树
- 二叉树路径节点关键值和等于目标值(LeetCode--112&LeetCode--113)