马上加入IBC程序猿 各种源码随意下,各种教程随便看! 注册 每日签到 加入编程讨论群

C#教程 ASP.NET教程 C#视频教程程序源码享受不尽 C#技术求助 ASP.NET技术求助

【源码下载】 社群合作 申请版主 程序开发 【远程协助】 每天乐一乐 每日签到 【承接外包项目】 面试-葵花宝典下载

官方一群:

官方二群:

C# 表达式树遍历

[复制链接]
查看2311 | 回复0 | 2019-9-17 11:29:35 | 显示全部楼层 |阅读模式

一、媒介

上一篇我们对表达式树有了开端的认识,这里我们将对表达式树举行遍历,只有弄清楚了他的运行原理,我们才可以对他举行定制化修改。

表达式系列目录

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 文件只在重写方法里面添加日记打印。

代码如下:

  1. public class SnailExpressionVisitor : ExpressionVisitor
  2. {
  3. public override Expression Visit(Expression node)
  4. {
  5. Console.WriteLine($"访问了 Visit,内容:{node.ToString()}");
  6. return base.Visit(node);
  7. }
  8. protected override CatchBlock VisitCatchBlock(CatchBlock node)
  9. {
  10. Console.WriteLine($"访问了 VisitCatchBlock,内容:{node.ToString()}");
  11. return base.VisitCatchBlock(node);
  12. }
  13. protected override ElementInit VisitElementInit(ElementInit node)
  14. {
  15. Console.WriteLine($"访问了 VisitElementInit,内容:{node.ToString()}");
  16. return base.VisitElementInit(node);
  17. }
  18. protected override LabelTarget VisitLabelTarget(LabelTarget node)
  19. {
  20. Console.WriteLine($"访问了 VisitLabelTarget,内容:{node.ToString()}");
  21. return base.VisitLabelTarget(node);
  22. }
  23. protected override MemberAssignment VisitMemberAssignment(MemberAssignment node)
  24. {
  25. Console.WriteLine($"访问了 VisitMemberAssignment,内容:{node.ToString()}");
  26. return base.VisitMemberAssignment(node);
  27. }
  28. protected override MemberBinding VisitMemberBinding(MemberBinding node)
  29. {
  30. Console.WriteLine($"访问了 VisitMemberBinding,内容:{node.ToString()}");
  31. return base.VisitMemberBinding(node);
  32. }
  33. protected override MemberListBinding VisitMemberListBinding(MemberListBinding node)
  34. {
  35. Console.WriteLine($"访问了 VisitMemberListBinding,内容:{node.ToString()}");
  36. return base.VisitMemberListBinding(node);
  37. }
  38. protected override MemberMemberBinding VisitMemberMemberBinding(MemberMemberBinding node)
  39. {
  40. Console.WriteLine($"访问了 VisitMemberMemberBinding,内容:{node.ToString()}");
  41. return base.VisitMemberMemberBinding(node);
  42. }
  43. protected override SwitchCase VisitSwitchCase(SwitchCase node)
  44. {
  45. Console.WriteLine($"访问了 VisitSwitchCase,内容:{node.ToString()}");
  46. return base.VisitSwitchCase(node);
  47. }
  48. protected override Expression VisitBinary(BinaryExpression node)
  49. {
  50. Console.WriteLine($"访问了 VisitBinary,内容:{node.ToString()}");
  51. return base.VisitBinary(node);
  52. }
  53. protected override Expression VisitBlock(BlockExpression node)
  54. {
  55. Console.WriteLine($"访问了 VisitBlock,内容:{node.ToString()}");
  56. return base.VisitBlock(node);
  57. }
  58. protected override Expression VisitConditional(ConditionalExpression node)
  59. {
  60. Console.WriteLine($"访问了 VisitConditional,内容:{node.ToString()}");
  61. return base.VisitConditional(node);
  62. }
  63. protected override Expression VisitConstant(ConstantExpression node)
  64. {
  65. Console.WriteLine($"访问了 VisitConstant,内容:{node.ToString()}");
  66. return base.VisitConstant(node);
  67. }
  68. protected override Expression VisitDebugInfo(DebugInfoExpression node)
  69. {
  70. Console.WriteLine($"访问了 VisitDebugInfo,内容:{node.ToString()}");
  71. return base.VisitDebugInfo(node);
  72. }
  73. protected override Expression VisitDefault(DefaultExpression node)
  74. {
  75. Console.WriteLine($"访问了 VisitDefault,内容:{node.ToString()}");
  76. return base.VisitDefault(node);
  77. }
  78. protected override Expression VisitDynamic(DynamicExpression node)
  79. {
  80. Console.WriteLine($"访问了 VisitDynamic,内容:{node.ToString()}");
  81. return base.VisitDynamic(node);
  82. }
  83. protected override Expression VisitExtension(Expression node)
  84. {
  85. Console.WriteLine($"访问了 VisitExtension,内容:{node.ToString()}");
  86. return base.VisitExtension(node);
  87. }
  88. protected override Expression VisitGoto(GotoExpression node)
  89. {
  90. Console.WriteLine($"访问了 VisitGoto,内容:{node.ToString()}");
  91. return base.VisitGoto(node);
  92. }
  93. protected override Expression VisitIndex(IndexExpression node)
  94. {
  95. Console.WriteLine($"访问了 VisitIndex,内容:{node.ToString()}");
  96. return base.VisitIndex(node);
  97. }
  98. protected override Expression VisitInvocation(InvocationExpression node)
  99. {
  100. Console.WriteLine($"访问了 VisitInvocation,内容:{node.ToString()}");
  101. return base.VisitInvocation(node);
  102. }
  103. protected override Expression VisitLabel(LabelExpression node)
  104. {
  105. Console.WriteLine($"访问了 VisitLabel,内容:{node.ToString()}");
  106. return base.VisitLabel(node);
  107. }
  108. protected override Expression VisitLambda<T>(Expression<T> node)
  109. {
  110. Console.WriteLine($"访问了 VisitLambda,内容:{node.ToString()}");
  111. return base.VisitLambda(node);
  112. }
  113. protected override Expression VisitListInit(ListInitExpression node)
  114. {
  115. Console.WriteLine($"访问了 VisitListInit,内容:{node.ToString()}");
  116. return base.VisitListInit(node);
  117. }
  118. protected override Expression VisitLoop(LoopExpression node)
  119. {
  120. Console.WriteLine($"访问了 VisitLoop,内容:{node.ToString()}");
  121. return base.VisitLoop(node);
  122. }
  123. protected override Expression VisitMember(MemberExpression node)
  124. {
  125. Console.WriteLine($"访问了 VisitMember,内容:{node.ToString()}");
  126. return base.VisitMember(node);
  127. }
  128. protected override Expression VisitMemberInit(MemberInitExpression node)
  129. {
  130. Console.WriteLine($"访问了 VisitMemberInit,内容:{node.ToString()}");
  131. return base.VisitMemberInit(node);
  132. }
  133. protected override Expression VisitMethodCall(MethodCallExpression node)
  134. {
  135. Console.WriteLine($"访问了 VisitMethodCall,内容:{node.ToString()}");
  136. return base.VisitMethodCall(node);
  137. }
  138. protected override Expression VisitNew(NewExpression node)
  139. {
  140. Console.WriteLine($"访问了 VisitNew,内容:{node.ToString()}");
  141. return base.VisitNew(node);
  142. }
  143. protected override Expression VisitNewArray(NewArrayExpression node)
  144. {
  145. Console.WriteLine($"访问了 VisitNewArray,内容:{node.ToString()}");
  146. return base.VisitNewArray(node);
  147. }
  148. protected override Expression VisitParameter(ParameterExpression node)
  149. {
  150. Console.WriteLine($"访问了 VisitParameter,内容:{node.ToString()}");
  151. return base.VisitParameter(node);
  152. }
  153. protected override Expression VisitRuntimeVariables(RuntimeVariablesExpression node)
  154. {
  155. Console.WriteLine($"访问了 VisitRuntimeVariables,内容:{node.ToString()}");
  156. return base.VisitRuntimeVariables(node);
  157. }
  158. protected override Expression VisitSwitch(SwitchExpression node)
  159. {
  160. Console.WriteLine($"访问了 VisitSwitch,内容:{node.ToString()}");
  161. return base.VisitSwitch(node);
  162. }
  163. protected override Expression VisitTry(TryExpression node)
  164. {
  165. Console.WriteLine($"访问了 VisitTry,内容:{node.ToString()}");
  166. return base.VisitTry(node);
  167. }
  168. protected override Expression VisitTypeBinary(TypeBinaryExpression node)
  169. {
  170. Console.WriteLine($"访问了 VisitTypeBinary,内容:{node.ToString()}");
  171. return base.VisitTypeBinary(node);
  172. }
  173. protected override Expression VisitUnary(UnaryExpression node)
  174. {
  175. Console.WriteLine($"访问了 VisitUnary,内容:{node.ToString()}");
  176. return base.VisitUnary(node);
  177. }
  178. }
复制代码

调用方法:

  1. Expression<Func<int, int, bool>> fun = (x, y) => x - y > 5;
  2. var treeModifier = new SnailExpressionVisitor();
  3. Expression modifiedExpr = treeModifier.Visit(fun);
复制代码

运行结果:

113419z6oe8rrc2ka3qj2c.png

从打印的日记里面可以看出,

1、每次访问表达式类时,都会先去调用Visit函数,估计他是在Visit里面判定表达式类,然后在根据表达式类的范例,调用访问改表达式的函数

2、对Lambda表达式类,是先访问的是Expression。Expression是不是很熟悉,上一章说过他的作用是将强范例Lambda表达式表示为表达式树情势的数据结构,剖析成功之后才对表达式的访问

3、对于表达式先剖析的是左边,左边的内容剖析完了之后在剖析右边,如(x-y)>5,剖析的次序是:x-y=>x=>y=>5

2.2、修改表达式树

既然我们弄清楚了表达式树的访问,如今我们就可以对他举行编辑修改了。

上面我们判断的是x-y>5,如今我们规定,将“-”改成“+”,“>”改成“>=”

对VisitBinary方法修改代码如下:

  1. protected override Expression VisitBinary(BinaryExpression node)
  2. {
  3. Console.WriteLine($"访问了 VisitBinary,内容:{node.ToString()}");
  4. if (node.NodeType == ExpressionType.GreaterThan)
  5. {
  6. Expression left = this.Visit(node.Left);
  7. Expression right = this.Visit(node.Right);
  8. var result = Expression.MakeBinary(ExpressionType.GreaterThanOrEqual, left, right, node.IsLiftedToNull, node.Method);
  9. Console.WriteLine($"访问了 VisitBinary,更改之后的内容:{result.ToString()}");
  10. return result;
  11. }
  12. else if (node.NodeType == ExpressionType.Subtract || node.NodeType == ExpressionType.SubtractChecked)
  13. {
  14. Expression left = this.Visit(node.Left);
  15. Expression right = this.Visit(node.Right);
  16. var result = Expression.MakeBinary(ExpressionType.Add, left, right, node.IsLiftedToNull, node.Method);
  17. Console.WriteLine($"访问了 VisitBinary,更改之后的内容:{result.ToString()}");
  18. return result;
  19. }
  20. else
  21. {
  22. return base.VisitBinary(node);
  23. }
  24. }
复制代码

调用方法:

  1. Expression<Func<int, int, bool>> fun = (x, y) => x - y > 5;
  2. var treeModifier = new SnailExpressionVisitor();
  3. Expression modifiedExpr = treeModifier.Visit(fun);
  4. Console.WriteLine($"Lambda的转换末了结果:{modifiedExpr.ToString()}");
复制代码

运行结果如下

113420yaaazragkkzhypia.png

三、总结

对表达树的解说已经完成了,但是说了这么久,对真实的开发有什么作用呢?反面我将使用Lambda表达式写一个对现有数据分页的公共方法,同时在对Dapper的扩展也会用到相干知识点,各人拭目以待吧……







来源:https://www.cnblogs.com/snailblog/archive/2019/09/15/11521335.html
C#论坛 www.ibcibc.com IBC编程社区
C#
C#论坛
IBC编程社区
*滑块验证:
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则