1 namespace System.Web.Mvc.ExpressionUtil {
3 using System.Collections.Generic;
4 using System.Linq.Expressions;
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.
9 internal sealed class HoistingExpressionVisitor<TIn, TOut> : ExpressionVisitor {
11 private static readonly ParameterExpression _hoistedConstantsParamExpr = Expression.Parameter(typeof(List<object>), "hoistedConstants");
12 private int _numConstantsProcessed;
14 // factory will create instance
15 private HoistingExpressionVisitor() { }
17 public static Expression<Hoisted<TIn, TOut>> Hoist(Expression<Func<TIn, TOut>> expr) {
18 // rewrite Expression<Func<TIn, TOut>> as Expression<Hoisted<TIn, TOut>>
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;
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);