/// <summary> /// Replace all the independent subtrees in an expression with /// constants equal to the expression's evaluated result. /// </summary> /// <param name="expression"> /// The expression to partially evaluate. /// </param> /// <param name="subtrees"> /// The independent subtrees in the expression. /// Change HashSet to List in wp7 SDK /// </param> /// <returns> /// An expression that depends only on parameter values. /// </returns> private static Expression EvaluateIndependentSubtrees(Expression expression, List <Expression> subtrees) { // Walk top down checking each node to see if it's the root of an // indedent subtree. Once we find one, we'll compile it and // replace the whole subtree with a constant. return(VisitorHelper.VisitAll( expression, (expr, recur) => { if (expr != null && subtrees.Contains(expr) && expr.NodeType != ExpressionType.Constant) { // Turn the expression into a parameterless lambda, // evaluate it, and return the response as a constant. Delegate compiled = Expression.Lambda(expr).Compile(); object value = compiled.DynamicInvoke(); return Expression.Constant(value, expr.Type); } else { return recur(expr); } })); }
/// <summary> /// Walk the expression and compute all of the subtrees that are not /// dependent on any of the expressions parameters. /// </summary> /// <param name="expression">The expression to analyze.</param> /// <returns> /// A set of all the expression subtrees that are independent from the /// expression's parameters. Note that this set will include every /// element of an independent subtree, but it's not a problem because /// the EvaluateIndependentSubtrees walks top down. /// /// Change HashSet to List in wp7 SDK /// </returns> private static List <Expression> FindIndependentSubtrees(Expression expression) { List <Expression> subtrees = new List <Expression>(); // The dependent flag is closed over and used to communicate // between different layers of the recursive call bool dependent = false; // Walk the tree finding every VisitorHelper.VisitAll( expression, (expr, recur) => { if (expr != null) { // Cache whether or not our parent is already dependent // because we're going to reset the flag while we // evalute our descendents to see if all of our // subtrees are independent. bool parentIsDependent = dependent; // Set dependent to false and visit my entire subtree // to see if anything sets it to true dependent = false; recur(expr); // If nothing in my subtree is dependent if (!dependent) { // Then the current node is independent if it's not // related to the parameter or if it's not the // constant query root (to handle degenerate cases // where we don't actually use any parameters in // the query - like table.skip(2).take(3)). ConstantExpression constant = expr as ConstantExpression; if (expr.NodeType == ExpressionType.Parameter || (constant != null && constant.Value is IQueryable)) { dependent = true; } else { // Then the whole subtree starting at this node // is independent of any expression parameters // and safe for partial evaluation subtrees.Add(expr); } } dependent |= parentIsDependent; } return(expr); }); return(subtrees); }
/// <summary> /// Walk the expression and compute all of the subtrees that are not /// dependent on any of the expressions parameters. /// </summary> /// <param name="expression">The expression to analyze.</param> /// <returns> /// A set of all the expression subtrees that are independent from the /// expression's parameters. Note that this set will include every /// element of an independent subtree, but it's not a problem because /// the EvaluateIndependentSubtrees walks top down. /// </returns> private static List <Expression> FindIndependentSubtrees(Expression expression) { List <Expression> subtrees = new List <Expression>(); // The dependent and isMemberInit flags are closed over and used to communicate // between different layers of the recursive call bool dependent = false; bool isMemberInit = false; // Walk the tree finding every VisitorHelper.VisitAll( expression, (expr, recur) => { if (expr != null) { // Cache whether or not our parent is already dependent // or a MemberInitExpression because we're going to reset // the flags while we evalute our descendents to see if all // of our subtrees are independent. bool parentIsDependent = dependent; bool parentIsMemberInit = isMemberInit; // Set flags to false and visit my entire subtree // to see if anything sets it to true dependent = false; isMemberInit = expr is MemberInitExpression; recur(expr); // If nothing in my subtree is dependent if (!dependent) { // A NewExpression itself will appear to be independent, // but if the parent is a MemberInitExpression, the NewExpression // can't be evaluated by itself. The MemberInitExpression will // determine if the full expression is dependent or not, so // the NewExpression should simply not be checked for dependency. if (expr is NewExpression newExpression && parentIsMemberInit) { return(expr); } // Then the current node is independent if it's not // related to the parameter or if it's not the // constant query root (to handle degenerate cases // where we don't actually use any parameters in // the query - like table.skip(2).take(3)). ConstantExpression constant = expr as ConstantExpression; if (expr.NodeType == ExpressionType.Parameter || (constant != null && constant.Value is IQueryable)) { dependent = true; } else { // Then the whole subtree starting at this node // is independent of any expression parameters // and safe for partial evaluation subtrees.Add(expr); } }