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