ExpressionVisitor.cs 14 KB

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