/// <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 HashSet <Expression> FindIndependentSubtrees(Expression expression)
        {
            HashSet <Expression> subtrees = new HashSet <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>
        /// Add a projection to the query.
        /// </summary>
        /// <param name="expression">Select method call expression.</param>
        private void AddProjection(MethodCallExpression expression)
        {
            // We only support Select(x => ...) projections.  Anything else
            // will throw a NotSupportException.
            if (expression != null && expression.Arguments.Count == 2)
            {
                LambdaExpression projection = StripQuote(expression.Arguments[1]) as LambdaExpression;
                if (projection != null && projection.Parameters.Count == 1)
                {
                    // Store the type of the input to the projection as we'll
                    // need that for deserialization of values (since the
                    // projection will change the expected type of the data
                    // source)
                    this.query.ProjectionArgumentType = projection.Parameters[0].Type;

                    // Compile the projection into a function that we can apply
                    // to the deserialized value to transform it accordingly.
                    this.query.Projection = projection.Compile();

                    // Filter the selection down to just the values used by
                    // the projection
                    VisitorHelper.VisitMembers(
                        projection.Body,
                        (expr, recur) =>
                    {
                        // Ensure we only process members of the parameter
                        if (expr != null && expr.Expression.NodeType == ExpressionType.Parameter)
                        {
                            SerializableMember member = SerializableType.GetMember(expr.Member);
                            if (member != null)
                            {
                                query.Selection.Add(member.Name);
                            }
                        }
                        return(recur(expr));
                    });

                    // Make sure we also include all the members that would be
                    // required for deserialization
                    foreach (SerializableMember member in
                             SerializableType.Get(this.query.ProjectionArgumentType)
                             .Members
                             .Select(p => p.Value)
                             .Where(m => m.IsRequired))
                    {
                        if (!this.query.Selection.Contains(member.Name))
                        {
                            this.query.Selection.Add(member.Name);
                        }
                    }

                    return;
                }
            }

            ThrowForUnsupportedException(expression);
        }
        /// <summary>
        /// Returns the MemberExpressions in the expression hierarchy of the <paramref name="expression"/>.
        /// </summary>
        /// <param name="expression">The expression to search for children MemberExpressions</param>
        /// <returns>A collection of MemberExpressions.</returns>
        public IEnumerable <MemberExpression> GetMemberExpressions(Expression expression)
        {
            List <MemberExpression> members = new List <MemberExpression>();

            VisitorHelper.VisitMembers(
                expression,
                (expr, recur) =>
            {
                // Ensure we only process members of the parameter
                if (expr is MemberExpression)
                {
                    members.Add((MemberExpression)expr);
                }

                return(recur(expr));
            });

            return(members);
        }
        /// <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);
                        }
                    }