ExpressionVisitor.cs 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375
  1. // Licensed to the .NET Foundation under one or more agreements.
  2. // The .NET Foundation licenses this file to you under the Apache 2.0 License.
  3. // See the LICENSE file in the project root for more information.
  4. #if NO_EXPRESSIONVISITOR
  5. using System;
  6. using System.Collections.Generic;
  7. using System.Collections.ObjectModel;
  8. using System.Reflection;
  9. using System.Linq.Expressions;
  10. namespace System.Reactive.Linq
  11. {
  12. internal abstract class ExpressionVisitor
  13. {
  14. internal ExpressionVisitor()
  15. {
  16. }
  17. public virtual Expression Visit(Expression exp)
  18. {
  19. if (exp == null)
  20. return exp;
  21. switch (exp.NodeType)
  22. {
  23. case ExpressionType.UnaryPlus:
  24. case ExpressionType.Negate:
  25. case ExpressionType.NegateChecked:
  26. case ExpressionType.Not:
  27. case ExpressionType.Convert:
  28. case ExpressionType.ConvertChecked:
  29. case ExpressionType.ArrayLength:
  30. case ExpressionType.Quote:
  31. case ExpressionType.TypeAs:
  32. return this.VisitUnary((UnaryExpression)exp);
  33. case ExpressionType.Add:
  34. case ExpressionType.AddChecked:
  35. case ExpressionType.Subtract:
  36. case ExpressionType.SubtractChecked:
  37. case ExpressionType.Multiply:
  38. case ExpressionType.MultiplyChecked:
  39. case ExpressionType.Divide:
  40. case ExpressionType.Modulo:
  41. case ExpressionType.Power:
  42. case ExpressionType.And:
  43. case ExpressionType.AndAlso:
  44. case ExpressionType.Or:
  45. case ExpressionType.OrElse:
  46. case ExpressionType.LessThan:
  47. case ExpressionType.LessThanOrEqual:
  48. case ExpressionType.GreaterThan:
  49. case ExpressionType.GreaterThanOrEqual:
  50. case ExpressionType.Equal:
  51. case ExpressionType.NotEqual:
  52. case ExpressionType.Coalesce:
  53. case ExpressionType.ArrayIndex:
  54. case ExpressionType.RightShift:
  55. case ExpressionType.LeftShift:
  56. case ExpressionType.ExclusiveOr:
  57. return this.VisitBinary((BinaryExpression)exp);
  58. case ExpressionType.TypeIs:
  59. return this.VisitTypeIs((TypeBinaryExpression)exp);
  60. case ExpressionType.Conditional:
  61. return this.VisitConditional((ConditionalExpression)exp);
  62. case ExpressionType.Constant:
  63. return this.VisitConstant((ConstantExpression)exp);
  64. case ExpressionType.Parameter:
  65. return this.VisitParameter((ParameterExpression)exp);
  66. case ExpressionType.MemberAccess:
  67. return this.VisitMemberAccess((MemberExpression)exp);
  68. case ExpressionType.Call:
  69. return this.VisitMethodCall((MethodCallExpression)exp);
  70. case ExpressionType.Lambda:
  71. return this.VisitLambda((LambdaExpression)exp);
  72. case ExpressionType.New:
  73. return this.VisitNew((NewExpression)exp);
  74. case ExpressionType.NewArrayInit:
  75. case ExpressionType.NewArrayBounds:
  76. return this.VisitNewArray((NewArrayExpression)exp);
  77. case ExpressionType.Invoke:
  78. return this.VisitInvocation((InvocationExpression)exp);
  79. case ExpressionType.MemberInit:
  80. return this.VisitMemberInit((MemberInitExpression)exp);
  81. case ExpressionType.ListInit:
  82. return this.VisitListInit((ListInitExpression)exp);
  83. default:
  84. throw new InvalidOperationException();
  85. }
  86. }
  87. protected virtual MemberBinding VisitBinding(MemberBinding binding)
  88. {
  89. switch (binding.BindingType)
  90. {
  91. case MemberBindingType.Assignment:
  92. return this.VisitMemberAssignment((MemberAssignment)binding);
  93. case MemberBindingType.MemberBinding:
  94. return this.VisitMemberMemberBinding((MemberMemberBinding)binding);
  95. case MemberBindingType.ListBinding:
  96. return this.VisitMemberListBinding((MemberListBinding)binding);
  97. default:
  98. throw new InvalidOperationException();
  99. }
  100. }
  101. protected virtual ElementInit VisitElementInitializer(ElementInit initializer)
  102. {
  103. ReadOnlyCollection<Expression> arguments = this.VisitExpressionList(initializer.Arguments);
  104. if (arguments != initializer.Arguments)
  105. {
  106. return Expression.ElementInit(initializer.AddMethod, arguments);
  107. }
  108. return initializer;
  109. }
  110. protected virtual Expression VisitUnary(UnaryExpression u)
  111. {
  112. Expression operand = this.Visit(u.Operand);
  113. if (operand != u.Operand)
  114. {
  115. return Expression.MakeUnary(u.NodeType, operand, u.Type, u.Method);
  116. }
  117. return u;
  118. }
  119. protected virtual Expression VisitBinary(BinaryExpression b)
  120. {
  121. Expression left = this.Visit(b.Left);
  122. Expression right = this.Visit(b.Right);
  123. Expression conversion = this.Visit(b.Conversion);
  124. if (left != b.Left || right != b.Right || conversion != b.Conversion)
  125. {
  126. if (b.NodeType == ExpressionType.Coalesce && b.Conversion != null)
  127. return Expression.Coalesce(left, right, conversion as LambdaExpression);
  128. else
  129. return Expression.MakeBinary(b.NodeType, left, right, b.IsLiftedToNull, b.Method);
  130. }
  131. return b;
  132. }
  133. protected virtual Expression VisitTypeIs(TypeBinaryExpression b)
  134. {
  135. Expression expr = this.Visit(b.Expression);
  136. if (expr != b.Expression)
  137. {
  138. return Expression.TypeIs(expr, b.TypeOperand);
  139. }
  140. return b;
  141. }
  142. protected virtual Expression VisitConstant(ConstantExpression c)
  143. {
  144. return c;
  145. }
  146. protected virtual Expression VisitConditional(ConditionalExpression c)
  147. {
  148. Expression test = this.Visit(c.Test);
  149. Expression ifTrue = this.Visit(c.IfTrue);
  150. Expression ifFalse = this.Visit(c.IfFalse);
  151. if (test != c.Test || ifTrue != c.IfTrue || ifFalse != c.IfFalse)
  152. {
  153. return Expression.Condition(test, ifTrue, ifFalse);
  154. }
  155. return c;
  156. }
  157. protected virtual Expression VisitParameter(ParameterExpression p)
  158. {
  159. return p;
  160. }
  161. protected virtual Expression VisitMemberAccess(MemberExpression m)
  162. {
  163. Expression exp = this.Visit(m.Expression);
  164. if (exp != m.Expression)
  165. {
  166. return Expression.MakeMemberAccess(exp, m.Member);
  167. }
  168. return m;
  169. }
  170. protected virtual Expression VisitMethodCall(MethodCallExpression m)
  171. {
  172. Expression obj = this.Visit(m.Object);
  173. IEnumerable<Expression> args = this.VisitExpressionList(m.Arguments);
  174. if (obj != m.Object || args != m.Arguments)
  175. {
  176. return Expression.Call(obj, m.Method, args);
  177. }
  178. return m;
  179. }
  180. protected virtual ReadOnlyCollection<Expression> VisitExpressionList(ReadOnlyCollection<Expression> original)
  181. {
  182. List<Expression> list = null;
  183. for (int i = 0, n = original.Count; i < n; i++)
  184. {
  185. Expression p = this.Visit(original[i]);
  186. if (list != null)
  187. {
  188. list.Add(p);
  189. }
  190. else if (p != original[i])
  191. {
  192. list = new List<Expression>(n);
  193. for (int j = 0; j < i; j++)
  194. {
  195. list.Add(original[j]);
  196. }
  197. list.Add(p);
  198. }
  199. }
  200. if (list != null)
  201. return new ReadOnlyCollection<Expression>(list);
  202. return original;
  203. }
  204. protected virtual MemberAssignment VisitMemberAssignment(MemberAssignment assignment)
  205. {
  206. Expression e = this.Visit(assignment.Expression);
  207. if (e != assignment.Expression)
  208. {
  209. return Expression.Bind(assignment.Member, e);
  210. }
  211. return assignment;
  212. }
  213. protected virtual MemberMemberBinding VisitMemberMemberBinding(MemberMemberBinding binding)
  214. {
  215. IEnumerable<MemberBinding> bindings = this.VisitBindingList(binding.Bindings);
  216. if (bindings != binding.Bindings)
  217. {
  218. return Expression.MemberBind(binding.Member, bindings);
  219. }
  220. return binding;
  221. }
  222. protected virtual MemberListBinding VisitMemberListBinding(MemberListBinding binding)
  223. {
  224. IEnumerable<ElementInit> initializers = this.VisitElementInitializerList(binding.Initializers);
  225. if (initializers != binding.Initializers)
  226. {
  227. return Expression.ListBind(binding.Member, initializers);
  228. }
  229. return binding;
  230. }
  231. protected virtual IEnumerable<MemberBinding> VisitBindingList(ReadOnlyCollection<MemberBinding> original)
  232. {
  233. List<MemberBinding> list = null;
  234. for (int i = 0, n = original.Count; i < n; i++)
  235. {
  236. MemberBinding b = this.VisitBinding(original[i]);
  237. if (list != null)
  238. {
  239. list.Add(b);
  240. }
  241. else if (b != original[i])
  242. {
  243. list = new List<MemberBinding>(n);
  244. for (int j = 0; j < i; j++)
  245. {
  246. list.Add(original[j]);
  247. }
  248. list.Add(b);
  249. }
  250. }
  251. if (list != null)
  252. return list;
  253. return original;
  254. }
  255. protected virtual IEnumerable<ElementInit> VisitElementInitializerList(ReadOnlyCollection<ElementInit> original)
  256. {
  257. List<ElementInit> list = null;
  258. for (int i = 0, n = original.Count; i < n; i++)
  259. {
  260. ElementInit init = this.VisitElementInitializer(original[i]);
  261. if (list != null)
  262. {
  263. list.Add(init);
  264. }
  265. else if (init != original[i])
  266. {
  267. list = new List<ElementInit>(n);
  268. for (int j = 0; j < i; j++)
  269. {
  270. list.Add(original[j]);
  271. }
  272. list.Add(init);
  273. }
  274. }
  275. if (list != null)
  276. return list;
  277. return original;
  278. }
  279. protected virtual Expression VisitLambda(LambdaExpression lambda)
  280. {
  281. Expression body = this.Visit(lambda.Body);
  282. if (body != lambda.Body)
  283. {
  284. return Expression.Lambda(lambda.Type, body, lambda.Parameters);
  285. }
  286. return lambda;
  287. }
  288. protected virtual NewExpression VisitNew(NewExpression nex)
  289. {
  290. IEnumerable<Expression> args = this.VisitExpressionList(nex.Arguments);
  291. if (args != nex.Arguments)
  292. {
  293. if (nex.Members != null)
  294. return Expression.New(nex.Constructor, args, nex.Members);
  295. else
  296. return Expression.New(nex.Constructor, args);
  297. }
  298. return nex;
  299. }
  300. protected virtual Expression VisitMemberInit(MemberInitExpression init)
  301. {
  302. NewExpression n = this.VisitNew(init.NewExpression);
  303. IEnumerable<MemberBinding> bindings = this.VisitBindingList(init.Bindings);
  304. if (n != init.NewExpression || bindings != init.Bindings)
  305. {
  306. return Expression.MemberInit(n, bindings);
  307. }
  308. return init;
  309. }
  310. protected virtual Expression VisitListInit(ListInitExpression init)
  311. {
  312. NewExpression n = this.VisitNew(init.NewExpression);
  313. IEnumerable<ElementInit> initializers = this.VisitElementInitializerList(init.Initializers);
  314. if (n != init.NewExpression || initializers != init.Initializers)
  315. {
  316. return Expression.ListInit(n, initializers);
  317. }
  318. return init;
  319. }
  320. protected virtual Expression VisitNewArray(NewArrayExpression na)
  321. {
  322. IEnumerable<Expression> exprs = this.VisitExpressionList(na.Expressions);
  323. if (exprs != na.Expressions)
  324. {
  325. if (na.NodeType == ExpressionType.NewArrayInit)
  326. {
  327. return Expression.NewArrayInit(na.Type.GetElementType(), exprs);
  328. }
  329. else
  330. {
  331. return Expression.NewArrayBounds(na.Type.GetElementType(), exprs);
  332. }
  333. }
  334. return na;
  335. }
  336. protected virtual Expression VisitInvocation(InvocationExpression iv)
  337. {
  338. IEnumerable<Expression> args = this.VisitExpressionList(iv.Arguments);
  339. Expression expr = this.Visit(iv.Expression);
  340. if (args != iv.Arguments || expr != iv.Expression)
  341. {
  342. return Expression.Invoke(expr, args);
  343. }
  344. return iv;
  345. }
  346. }
  347. }
  348. #endif