PageRenderTime 375ms CodeModel.GetById 28ms RepoModel.GetById 0ms app.codeStats 0ms

/mcs/class/System.Web.Mvc3/Mvc/ExpressionUtil/FingerprintingExpressionVisitor.cs

https://bitbucket.org/danipen/mono
C# | 220 lines | 167 code | 47 blank | 6 comment | 17 complexity | 6790a62eaaa188a11f0db0c8ab313361 MD5 | raw file
Possible License(s): Unlicense, Apache-2.0, LGPL-2.0, MPL-2.0-no-copyleft-exception, CC-BY-SA-3.0, GPL-2.0
  1. namespace System.Web.Mvc.ExpressionUtil {
  2. using System;
  3. using System.Collections.Generic;
  4. using System.Linq.Expressions;
  5. // This is a visitor which produces a fingerprint of an expression. It doesn't
  6. // rewrite the expression in a form which can be compiled and cached.
  7. internal sealed class FingerprintingExpressionVisitor : ExpressionVisitor {
  8. private readonly List<object> _seenConstants = new List<object>();
  9. private readonly List<ParameterExpression> _seenParameters = new List<ParameterExpression>();
  10. private readonly ExpressionFingerprintChain _currentChain = new ExpressionFingerprintChain();
  11. private bool _gaveUp;
  12. private FingerprintingExpressionVisitor() { }
  13. private T GiveUp<T>(T node) {
  14. // We don't understand this node, so just quit.
  15. _gaveUp = true;
  16. return node;
  17. }
  18. // Returns the fingerprint chain + captured constants list for this expression, or null
  19. // if the expression couldn't be fingerprinted.
  20. public static ExpressionFingerprintChain GetFingerprintChain(Expression expr, out List<object> capturedConstants) {
  21. FingerprintingExpressionVisitor visitor = new FingerprintingExpressionVisitor();
  22. visitor.Visit(expr);
  23. if (visitor._gaveUp) {
  24. capturedConstants = null;
  25. return null;
  26. }
  27. else {
  28. capturedConstants = visitor._seenConstants;
  29. return visitor._currentChain;
  30. }
  31. }
  32. public override Expression Visit(Expression node) {
  33. if (node == null) {
  34. _currentChain.Elements.Add(null);
  35. return null;
  36. }
  37. else {
  38. return base.Visit(node);
  39. }
  40. }
  41. protected override Expression VisitBinary(BinaryExpression node) {
  42. if (_gaveUp) { return node; }
  43. _currentChain.Elements.Add(new BinaryExpressionFingerprint(node.NodeType, node.Type, node.Method));
  44. return base.VisitBinary(node);
  45. }
  46. protected override Expression VisitBlock(BlockExpression node) {
  47. return GiveUp(node);
  48. }
  49. protected override CatchBlock VisitCatchBlock(CatchBlock node) {
  50. return GiveUp(node);
  51. }
  52. protected override Expression VisitConditional(ConditionalExpression node) {
  53. if (_gaveUp) { return node; }
  54. _currentChain.Elements.Add(new ConditionalExpressionFingerprint(node.NodeType, node.Type));
  55. return base.VisitConditional(node);
  56. }
  57. protected override Expression VisitConstant(ConstantExpression node) {
  58. if (_gaveUp) { return node; }
  59. _seenConstants.Add(node.Value);
  60. _currentChain.Elements.Add(new ConstantExpressionFingerprint(node.NodeType, node.Type));
  61. return base.VisitConstant(node);
  62. }
  63. protected override Expression VisitDebugInfo(DebugInfoExpression node) {
  64. return GiveUp(node);
  65. }
  66. protected override Expression VisitDefault(DefaultExpression node) {
  67. if (_gaveUp) { return node; }
  68. _currentChain.Elements.Add(new DefaultExpressionFingerprint(node.NodeType, node.Type));
  69. return base.VisitDefault(node);
  70. }
  71. protected override Expression VisitDynamic(DynamicExpression node) {
  72. return GiveUp(node);
  73. }
  74. protected override ElementInit VisitElementInit(ElementInit node) {
  75. return GiveUp(node);
  76. }
  77. protected override Expression VisitExtension(Expression node) {
  78. return GiveUp(node);
  79. }
  80. protected override Expression VisitGoto(GotoExpression node) {
  81. return GiveUp(node);
  82. }
  83. protected override Expression VisitIndex(IndexExpression node) {
  84. if (_gaveUp) { return node; }
  85. _currentChain.Elements.Add(new IndexExpressionFingerprint(node.NodeType, node.Type, node.Indexer));
  86. return base.VisitIndex(node);
  87. }
  88. protected override Expression VisitInvocation(InvocationExpression node) {
  89. return GiveUp(node);
  90. }
  91. protected override Expression VisitLabel(LabelExpression node) {
  92. return GiveUp(node);
  93. }
  94. protected override LabelTarget VisitLabelTarget(LabelTarget node) {
  95. return GiveUp(node);
  96. }
  97. protected override Expression VisitLambda<T>(Expression<T> node) {
  98. if (_gaveUp) { return node; }
  99. _currentChain.Elements.Add(new LambdaExpressionFingerprint(node.NodeType, node.Type));
  100. return base.VisitLambda<T>(node);
  101. }
  102. protected override Expression VisitListInit(ListInitExpression node) {
  103. return GiveUp(node);
  104. }
  105. protected override Expression VisitLoop(LoopExpression node) {
  106. return GiveUp(node);
  107. }
  108. protected override Expression VisitMember(MemberExpression node) {
  109. if (_gaveUp) { return node; }
  110. _currentChain.Elements.Add(new MemberExpressionFingerprint(node.NodeType, node.Type, node.Member));
  111. return base.VisitMember(node);
  112. }
  113. protected override MemberAssignment VisitMemberAssignment(MemberAssignment node) {
  114. return GiveUp(node);
  115. }
  116. protected override MemberBinding VisitMemberBinding(MemberBinding node) {
  117. return GiveUp(node);
  118. }
  119. protected override Expression VisitMemberInit(MemberInitExpression node) {
  120. return GiveUp(node);
  121. }
  122. protected override MemberListBinding VisitMemberListBinding(MemberListBinding node) {
  123. return GiveUp(node);
  124. }
  125. protected override MemberMemberBinding VisitMemberMemberBinding(MemberMemberBinding node) {
  126. return GiveUp(node);
  127. }
  128. protected override Expression VisitMethodCall(MethodCallExpression node) {
  129. if (_gaveUp) { return node; }
  130. _currentChain.Elements.Add(new MethodCallExpressionFingerprint(node.NodeType, node.Type, node.Method));
  131. return base.VisitMethodCall(node);
  132. }
  133. protected override Expression VisitNew(NewExpression node) {
  134. return GiveUp(node);
  135. }
  136. protected override Expression VisitNewArray(NewArrayExpression node) {
  137. return GiveUp(node);
  138. }
  139. protected override Expression VisitParameter(ParameterExpression node) {
  140. if (_gaveUp) { return node; }
  141. int parameterIndex = _seenParameters.IndexOf(node);
  142. if (parameterIndex < 0) {
  143. // first time seeing this parameter
  144. parameterIndex = _seenParameters.Count;
  145. _seenParameters.Add(node);
  146. }
  147. _currentChain.Elements.Add(new ParameterExpressionFingerprint(node.NodeType, node.Type, parameterIndex));
  148. return base.VisitParameter(node);
  149. }
  150. protected override Expression VisitRuntimeVariables(RuntimeVariablesExpression node) {
  151. return GiveUp(node);
  152. }
  153. protected override Expression VisitSwitch(SwitchExpression node) {
  154. return GiveUp(node);
  155. }
  156. protected override SwitchCase VisitSwitchCase(SwitchCase node) {
  157. return GiveUp(node);
  158. }
  159. protected override Expression VisitTry(TryExpression node) {
  160. return GiveUp(node);
  161. }
  162. protected override Expression VisitTypeBinary(TypeBinaryExpression node) {
  163. if (_gaveUp) { return node; }
  164. _currentChain.Elements.Add(new TypeBinaryExpressionFingerprint(node.NodeType, node.Type, node.TypeOperand));
  165. return base.VisitTypeBinary(node);
  166. }
  167. protected override Expression VisitUnary(UnaryExpression node) {
  168. if (_gaveUp) { return node; }
  169. _currentChain.Elements.Add(new UnaryExpressionFingerprint(node.NodeType, node.Type, node.Method));
  170. return base.VisitUnary(node);
  171. }
  172. }
  173. }