19 using System.Collections.Generic;
20 using System.Collections.ObjectModel;
21 using System.Linq.Expressions;
23 namespace Deveel.Data.Linq {
28 public virtual Expression
Visit(Expression exp) {
31 switch (exp.NodeType) {
32 case ExpressionType.Negate:
33 case ExpressionType.NegateChecked:
34 case ExpressionType.Not:
35 case ExpressionType.Convert:
36 case ExpressionType.ConvertChecked:
37 case ExpressionType.ArrayLength:
38 case ExpressionType.Quote:
39 case ExpressionType.TypeAs:
40 return this.VisitUnary((UnaryExpression)exp);
41 case ExpressionType.Add:
42 case ExpressionType.AddChecked:
43 case ExpressionType.Subtract:
44 case ExpressionType.SubtractChecked:
45 case ExpressionType.Multiply:
46 case ExpressionType.MultiplyChecked:
47 case ExpressionType.Divide:
48 case ExpressionType.Modulo:
49 case ExpressionType.And:
50 case ExpressionType.AndAlso:
51 case ExpressionType.Or:
52 case ExpressionType.OrElse:
53 case ExpressionType.LessThan:
54 case ExpressionType.LessThanOrEqual:
55 case ExpressionType.GreaterThan:
56 case ExpressionType.GreaterThanOrEqual:
57 case ExpressionType.Equal:
58 case ExpressionType.NotEqual:
59 case ExpressionType.Coalesce:
60 case ExpressionType.ArrayIndex:
61 case ExpressionType.RightShift:
62 case ExpressionType.LeftShift:
63 case ExpressionType.ExclusiveOr:
64 return VisitBinary((BinaryExpression)exp);
65 case ExpressionType.TypeIs:
66 return VisitTypeIs((TypeBinaryExpression)exp);
67 case ExpressionType.Conditional:
68 return VisitConditional((ConditionalExpression)exp);
69 case ExpressionType.Constant:
70 return VisitConstant((ConstantExpression)exp);
71 case ExpressionType.Parameter:
72 return VisitParameter((ParameterExpression)exp);
73 case ExpressionType.MemberAccess:
74 return VisitMemberAccess((MemberExpression)exp);
75 case ExpressionType.Call:
76 return VisitMethodCall((MethodCallExpression)exp);
77 case ExpressionType.Lambda:
78 return VisitLambda((LambdaExpression)exp);
79 case ExpressionType.New:
80 return VisitNew((NewExpression)exp);
81 case ExpressionType.NewArrayInit:
82 case ExpressionType.NewArrayBounds:
83 return VisitNewArray((NewArrayExpression)exp);
84 case ExpressionType.Invoke:
85 return VisitInvocation((InvocationExpression)exp);
86 case ExpressionType.MemberInit:
87 return VisitMemberInit((MemberInitExpression)exp);
88 case ExpressionType.ListInit:
89 return VisitListInit((ListInitExpression)exp);
91 throw new Exception(
string.Format(
"Unhandled expression type: '{0}'", exp.NodeType));
95 protected virtual MemberBinding
VisitBinding(MemberBinding binding) {
96 switch (binding.BindingType) {
97 case MemberBindingType.Assignment:
98 return VisitMemberAssignment((MemberAssignment)binding);
99 case MemberBindingType.MemberBinding:
100 return VisitMemberMemberBinding((MemberMemberBinding)binding);
101 case MemberBindingType.ListBinding:
102 return VisitMemberListBinding((MemberListBinding)binding);
104 throw new Exception(
string.Format(
"Unhandled binding type '{0}'", binding.BindingType));
109 ReadOnlyCollection<Expression> arguments = VisitExpressionList(initializer.Arguments);
110 if (arguments != initializer.Arguments) {
111 return Expression.ElementInit(initializer.AddMethod, arguments);
117 Expression operand = Visit(u.Operand);
118 if (operand != u.Operand) {
119 return Expression.MakeUnary(u.NodeType, operand, u.Type, u.Method);
125 Expression left = Visit(b.Left);
126 Expression right = Visit(b.Right);
127 Expression conversion = Visit(b.Conversion);
128 if (left != b.Left || right != b.Right || conversion != b.Conversion) {
129 if (b.NodeType == ExpressionType.Coalesce && b.Conversion != null)
130 return Expression.Coalesce(left, right, conversion as LambdaExpression);
132 return Expression.MakeBinary(b.NodeType, left, right, b.IsLiftedToNull, b.Method);
137 protected virtual Expression
VisitTypeIs(TypeBinaryExpression b) {
138 Expression expr = Visit(b.Expression);
139 if (expr != b.Expression) {
140 return Expression.TypeIs(expr, b.TypeOperand);
150 Expression test = Visit(c.Test);
151 Expression ifTrue = Visit(c.IfTrue);
152 Expression ifFalse = Visit(c.IfFalse);
153 if (test != c.Test || ifTrue != c.IfTrue || ifFalse != c.IfFalse) {
154 return Expression.Condition(test, ifTrue, ifFalse);
164 Expression exp = this.Visit(m.Expression);
165 if (exp != m.Expression) {
166 return Expression.MakeMemberAccess(exp, m.Member);
172 Expression obj = this.Visit(m.Object);
173 IEnumerable<Expression> args = this.VisitExpressionList(m.Arguments);
174 if (obj != m.Object || args != m.Arguments) {
175 return Expression.Call(obj, m.Method, args);
180 protected virtual ReadOnlyCollection<Expression>
VisitExpressionList(ReadOnlyCollection<Expression> original) {
181 List<Expression> list = null;
182 for (
int i = 0, n = original.Count; i < n; i++) {
183 Expression p = this.Visit(original[i]);
186 }
else if (p != original[i]) {
187 list =
new List<Expression>(n);
188 for (
int j = 0; j < i; j++) {
189 list.Add(original[j]);
195 return list.AsReadOnly();
201 Expression e = this.Visit(assignment.Expression);
202 if (e != assignment.Expression) {
203 return Expression.Bind(assignment.Member, e);
209 IEnumerable<MemberBinding> bindings = this.VisitBindingList(binding.Bindings);
210 if (bindings != binding.Bindings) {
211 return Expression.MemberBind(binding.Member, bindings);
217 IEnumerable<ElementInit> initializers = this.VisitElementInitializerList(binding.Initializers);
218 if (initializers != binding.Initializers) {
219 return Expression.ListBind(binding.Member, initializers);
224 protected virtual IEnumerable<MemberBinding>
VisitBindingList(ReadOnlyCollection<MemberBinding> original) {
225 List<MemberBinding> list = null;
226 for (
int i = 0, n = original.Count; i < n; i++) {
227 MemberBinding b = this.VisitBinding(original[i]);
230 }
else if (b != original[i]) {
231 list =
new List<MemberBinding>(n);
232 for (
int j = 0; j < i; j++) {
233 list.Add(original[j]);
244 List<ElementInit> list = null;
245 for (
int i = 0, n = original.Count; i < n; i++) {
246 ElementInit init = this.VisitElementInitializer(original[i]);
249 }
else if (init != original[i]) {
250 list =
new List<ElementInit>(n);
251 for (
int j = 0; j < i; j++) {
252 list.Add(original[j]);
262 protected virtual Expression
VisitLambda(LambdaExpression lambda) {
263 Expression body = this.Visit(lambda.Body);
264 if (body != lambda.Body) {
265 return Expression.Lambda(lambda.Type, body, lambda.Parameters);
270 protected virtual NewExpression
VisitNew(NewExpression nex) {
271 IEnumerable<Expression> args = this.VisitExpressionList(nex.Arguments);
272 if (args != nex.Arguments) {
273 if (nex.Members != null)
274 return Expression.New(nex.Constructor, args, nex.Members);
276 return Expression.New(nex.Constructor, args);
282 NewExpression n = this.VisitNew(init.NewExpression);
283 IEnumerable<MemberBinding> bindings = this.VisitBindingList(init.Bindings);
284 if (n != init.NewExpression || bindings != init.Bindings) {
285 return Expression.MemberInit(n, bindings);
291 NewExpression n = this.VisitNew(init.NewExpression);
292 IEnumerable<ElementInit> initializers = this.VisitElementInitializerList(init.Initializers);
293 if (n != init.NewExpression || initializers != init.Initializers) {
294 return Expression.ListInit(n, initializers);
300 IEnumerable<Expression> exprs = this.VisitExpressionList(na.Expressions);
301 if (exprs != na.Expressions) {
302 if (na.NodeType == ExpressionType.NewArrayInit) {
303 return Expression.NewArrayInit(na.Type.GetElementType(), exprs);
305 return Expression.NewArrayBounds(na.Type.GetElementType(), exprs);
312 IEnumerable<Expression> args = this.VisitExpressionList(iv.Arguments);
313 Expression expr = this.Visit(iv.Expression);
314 if (args != iv.Arguments || expr != iv.Expression) {
315 return Expression.Invoke(expr, args);
virtual IEnumerable< MemberBinding > VisitBindingList(ReadOnlyCollection< MemberBinding > original)
virtual Expression VisitTypeIs(TypeBinaryExpression b)
virtual Expression VisitParameter(ParameterExpression p)
virtual MemberBinding VisitBinding(MemberBinding binding)
virtual MemberAssignment VisitMemberAssignment(MemberAssignment assignment)
virtual Expression VisitBinary(BinaryExpression b)
virtual MemberMemberBinding VisitMemberMemberBinding(MemberMemberBinding binding)
virtual IEnumerable< ElementInit > VisitElementInitializerList(ReadOnlyCollection< ElementInit > original)
virtual Expression VisitNewArray(NewArrayExpression na)
virtual Expression VisitListInit(ListInitExpression init)
virtual MemberListBinding VisitMemberListBinding(MemberListBinding binding)
virtual Expression VisitMethodCall(MethodCallExpression m)
virtual Expression VisitMemberInit(MemberInitExpression init)
virtual Expression VisitConditional(ConditionalExpression c)
virtual NewExpression VisitNew(NewExpression nex)
virtual Expression VisitInvocation(InvocationExpression iv)
virtual Expression Visit(Expression exp)
virtual Expression VisitMemberAccess(MemberExpression m)
virtual Expression VisitUnary(UnaryExpression u)
virtual Expression VisitLambda(LambdaExpression lambda)
virtual Expression VisitConstant(ConstantExpression c)
virtual ElementInit VisitElementInitializer(ElementInit initializer)
virtual ReadOnlyCollection< Expression > VisitExpressionList(ReadOnlyCollection< Expression > original)