一、媒介
上一篇我们对表达式树有了开端的认识,这里我们将对表达式树举行遍历,只有弄清楚了他的运行原理,我们才可以对他举行定制化修改。
表达式系列目录
C# 表达式树解说(一)
C# 表达式树遍历(二)
C# 表达式树分页扩展(三)
二、表达式树的遍历
要检察表达式树的遍历,肯定不能直接用.Net Framework封装的方法,因为.Net Framework框架是闭源的,除了看中间语言(IL)去检察。我们就用ExpressionVisitor类检察一下他的运行原理,看了下ExpressionVisitor类,里面都是对各个表达式的访问,而且都是虚拟函数,我们可以对他举行override。
ExpressionVisitor类里面都是对各个范例的表达式举行访问,为了更好的明白里面的访问次序,蜗牛把里面的虚函数都override了一遍,然后跟踪里面的实行次序。【傻眼了,35个虚函数必要override,内心是很拒绝的,vs2019有没有重写父类虚函数的快捷键啊!!!!!!!】
ExpressionVisitor类相干先容:https://docs.microsoft.com/zh-cn ... ew=netframework-4.8
2.1、ExpressionVisitor类的跟踪
为了不改变ExpressionVisitor类原来的访问,创建的SnailExpressionVisitor.cs 文件只在重写方法里面添加日记打印。
代码如下:
调用方法:
- Expression<Func<int, int, bool>> fun = (x, y) => x - y > 5;
- var treeModifier = new SnailExpressionVisitor();
- Expression modifiedExpr = treeModifier.Visit(fun);
复制代码
运行结果:
从打印的日记里面可以看出,
1、每次访问表达式类时,都会先去调用Visit函数,估计他是在Visit里面判定表达式类,然后在根据表达式类的范例,调用访问改表达式的函数
2、对Lambda表达式类,是先访问的是Expression。Expression是不是很熟悉,上一章说过他的作用是将强范例Lambda表达式表示为表达式树情势的数据结构,剖析成功之后才对表达式的访问
3、对于表达式先剖析的是左边,左边的内容剖析完了之后在剖析右边,如(x-y)>5,剖析的次序是:x-y=>x=>y=>5
2.2、修改表达式树
既然我们弄清楚了表达式树的访问,如今我们就可以对他举行编辑修改了。
上面我们判断的是x-y>5,如今我们规定,将“-”改成“+”,“>”改成“>=”
对VisitBinary方法修改代码如下:
- protected override Expression VisitBinary(BinaryExpression node)
- {
- Console.WriteLine($"访问了 VisitBinary,内容:{node.ToString()}");
- if (node.NodeType == ExpressionType.GreaterThan)
- {
- Expression left = this.Visit(node.Left);
- Expression right = this.Visit(node.Right);
- var result = Expression.MakeBinary(ExpressionType.GreaterThanOrEqual, left, right, node.IsLiftedToNull, node.Method);
- Console.WriteLine($"访问了 VisitBinary,更改之后的内容:{result.ToString()}");
- return result;
- }
- else if (node.NodeType == ExpressionType.Subtract || node.NodeType == ExpressionType.SubtractChecked)
- {
- Expression left = this.Visit(node.Left);
- Expression right = this.Visit(node.Right);
- var result = Expression.MakeBinary(ExpressionType.Add, left, right, node.IsLiftedToNull, node.Method);
- Console.WriteLine($"访问了 VisitBinary,更改之后的内容:{result.ToString()}");
- return result;
- }
- else
- {
- return base.VisitBinary(node);
- }
- }
复制代码
调用方法:
- Expression<Func<int, int, bool>> fun = (x, y) => x - y > 5;
- var treeModifier = new SnailExpressionVisitor();
- Expression modifiedExpr = treeModifier.Visit(fun);
- Console.WriteLine($"Lambda的转换末了结果:{modifiedExpr.ToString()}");
复制代码
运行结果如下
三、总结
对表达树的解说已经完成了,但是说了这么久,对真实的开发有什么作用呢?反面我将使用Lambda表达式写一个对现有数据分页的公共方法,同时在对Dapper的扩展也会用到相干知识点,各人拭目以待吧……
来源:https://www.cnblogs.com/snailblog/archive/2019/09/15/11521335.html |