Merge pull request #249 from pcc/xgetinputfocus
[mono.git] / mcs / class / System.Web.Mvc3 / Mvc / ExpressionUtil / HoistingExpressionVisitor.cs
1 namespace System.Web.Mvc.ExpressionUtil {
2     using System;
3     using System.Collections.Generic;
4     using System.Linq.Expressions;
5
6     // This is a visitor which rewrites constant expressions as parameter lookups. It's meant
7     // to produce an expression which can be cached safely.
8
9     internal sealed class HoistingExpressionVisitor<TIn, TOut> : ExpressionVisitor {
10
11         private static readonly ParameterExpression _hoistedConstantsParamExpr = Expression.Parameter(typeof(List<object>), "hoistedConstants");
12         private int _numConstantsProcessed;
13
14         // factory will create instance
15         private HoistingExpressionVisitor() { }
16
17         public static Expression<Hoisted<TIn, TOut>> Hoist(Expression<Func<TIn, TOut>> expr) {
18             // rewrite Expression<Func<TIn, TOut>> as Expression<Hoisted<TIn, TOut>>
19
20             var visitor = new HoistingExpressionVisitor<TIn, TOut>();
21             var rewrittenBodyExpr = visitor.Visit(expr.Body);
22             var rewrittenLambdaExpr = Expression.Lambda<Hoisted<TIn, TOut>>(rewrittenBodyExpr, expr.Parameters[0], _hoistedConstantsParamExpr);
23             return rewrittenLambdaExpr;
24         }
25
26         protected override Expression VisitConstant(ConstantExpression node) {
27             // rewrite the constant expression as (TConst)hoistedConstants[i];
28             return Expression.Convert(Expression.Property(_hoistedConstantsParamExpr, "Item", Expression.Constant(_numConstantsProcessed++)), node.Type);
29         }
30
31     }
32 }