/// <summary>
        /// Analyzes the specified <paramref name="lambda"/> for selection and updates
        /// <paramref name="resource"/>.
        /// </summary>
        /// <param name="lambda">Lambda expression to analyze.</param>
        /// <param name="resource">Resource expression to update.</param>
        /// <param name="context">Context of expression to analyze.</param>
        private static void AnalyzeResourceExpression(LambdaExpression lambda, ResourceExpression resource, DataServiceContext context)
        {
            SelectExpandPathBuilder pb = new SelectExpandPathBuilder();

            ProjectionAnalyzer.Analyze(lambda, pb, context);
            resource.Projection  = new ProjectionQueryOptionExpression(lambda.Body.Type, lambda, pb.ProjectionPaths.ToList());
            resource.ExpandPaths = pb.ExpandPaths.Union(resource.ExpandPaths, StringComparer.Ordinal).ToList();
            resource.RaiseUriVersion(pb.UriVersion);
        }
            internal override Expression VisitMemberInit(MemberInitExpression init)
            {
                if (!ClientTypeUtil.TypeOrElementTypeIsEntity(init.Type))
                {
                    // MemberInit to a complex type is not supported on entity types.
                    throw new NotSupportedException(Strings.ALinq_ExpressionNotSupportedInProjectionToEntity(this.type, init.ToString()));
                }

                ProjectionAnalyzer.Analyze(init, this.builder, this.context);
                return(init);
            }
            internal override Expression VisitMethodCall(MethodCallExpression m)
            {
                // We throw NotSupportedException when IsDisallowedExceptionForMethodCall() is true
                // or we have a method call on a non-entity type, for example c.MyCollectionComplexProperty.Select(...)
                if ((m.Object != null && (IsDisallowedExpressionForMethodCall(m.Object, this.context.Model) || !ClientTypeUtil.TypeOrElementTypeIsEntity(m.Object.Type))) ||
                    m.Arguments.Any(a => IsDisallowedExpressionForMethodCall(a, this.context.Model)) ||
                    (m.Object == null && !ClientTypeUtil.TypeOrElementTypeIsEntity(m.Arguments[0].Type)))
                {
                    throw new NotSupportedException(Strings.ALinq_ExpressionNotSupportedInProjection(this.type, m.ToString()));
                }

                if (ProjectionAnalyzer.IsMethodCallAllowedEntitySequence(m))
                {
                    CheckChainedSequence(m, this.type);

                    // allow selects for following pattern:
                    // Orders = c.Orders.Select(o=> new NarrowOrder {...}).ToList();
                    return(base.VisitMethodCall(m));
                }

                throw new NotSupportedException(Strings.ALinq_ExpressionNotSupportedInProjectionToEntity(this.type, m.ToString()));
            }
            internal override Expression VisitMethodCall(MethodCallExpression m)
            {
                if ((m.Object != null && IsDisallowedExpressionForMethodCall(m.Object, this.context.Model)) ||
                    m.Arguments.Any(a => IsDisallowedExpressionForMethodCall(a, this.context.Model)))
                {
                    throw new NotSupportedException(Strings.ALinq_ExpressionNotSupportedInProjection(this.type, m.ToString()));
                }

                CheckChainedSequence(m, this.type);
                if (ProjectionAnalyzer.IsMethodCallAllowedEntitySequence(m))
                {
                    // allow IEnum.Select and IEnum.ToList even if entity type.
                    return(base.VisitMethodCall(m));
                }

                if ((m.Object != null ? ClientTypeUtil.TypeOrElementTypeIsEntity(m.Object.Type) : false) ||
                    m.Arguments.Any(a => ClientTypeUtil.TypeOrElementTypeIsEntity(a.Type)))
                {
                    throw new NotSupportedException(Strings.ALinq_ExpressionNotSupportedInProjection(this.type, m.ToString()));
                }

                return(base.VisitMethodCall(m));
            }
 internal override Expression VisitMemberInit(MemberInitExpression init)
 {
     ProjectionAnalyzer.Analyze(init, this.builder, this.context);
     return(init);
 }
 internal override Expression VisitLambda(LambdaExpression lambda)
 {
     ProjectionAnalyzer.Analyze(lambda, this.builder, this.context);
     return(lambda);
 }
        /// <summary>
        /// CODE: x
        /// ORIGINAL: Convert(x, t) where t is assignable from typeof(x)
        /// ORIGINAL: x as t, where t is assignable from typeof(x)
        /// ORIGINAL: and typeof(x) or t are not known primitives unless typeof(x) == t
        /// ORIGINAL: and x is not a collection of entity types
        /// ORIGINAL: and x is not a enum type
        /// NORMALIZED: x
        /// </summary>
        internal override Expression VisitUnary(UnaryExpression u)
        {
            UnaryExpression visited = (UnaryExpression)base.VisitUnary(u);
            Expression      result  = visited;

            // Note that typically we would record a potential rewrite
            // after extracting the conversion, but we avoid doing this
            // because it breaks undoing the rewrite by making the non-local
            // change circular, ie:
            //   unary [operand = a]
            // becomes
            //   a <- unary [operand = a]
            // So the undoing visits a, then the original unary, then the
            // operand and again the unary, the operand, etc.
            this.RecordRewrite(u, result);

            // Convert(x, t) or x as t, where t is assignable from typeof(x)
            if ((visited.NodeType == ExpressionType.Convert || visited.NodeType == ExpressionType.TypeAs) && visited.Type.IsAssignableFrom(visited.Operand.Type))
            {
                // typeof(x) or t are not known primitives unless typeof(x) == t
                if (!PrimitiveType.IsKnownNullableType(visited.Operand.Type) && !PrimitiveType.IsKnownNullableType(visited.Type) || visited.Operand.Type == visited.Type)
                {
                    // x is not a collection of entity types
                    if (!(ClientTypeUtil.TypeOrElementTypeIsEntity(visited.Operand.Type) && ProjectionAnalyzer.IsCollectionProducingExpression(visited.Operand)))
                    {
                        // x is not an enum type
                        if (!visited.Operand.Type.IsEnum)
                        {
                            result = visited.Operand;
                        }
                    }
                }
            }

            return(result);
        }