Example #1
0
            internal override Expression VisitMemberAccess(MemberExpression m)
            {
                PropertyInfo info;
                Expression   expression;
                Type         type = m.Expression.Type;

                this.leafExpressionIsMemberAccess = true;
                if (PrimitiveType.IsKnownNullableType(type))
                {
                    this.leafExpressionIsMemberAccess = false;
                    return(base.VisitMemberAccess(m));
                }
                if (ProjectionAnalyzer.IsCollectionProducingExpression(m.Expression))
                {
                    throw new NotSupportedException(System.Data.Services.Client.Strings.ALinq_ExpressionNotSupportedInProjection(this.type, m.ToString()));
                }
                if (!ResourceBinder.PatternRules.MatchNonPrivateReadableProperty(m, out info, out expression))
                {
                    throw new NotSupportedException(System.Data.Services.Client.Strings.ALinq_ExpressionNotSupportedInProjection(this.type, m.ToString()));
                }
                Expression expression2 = base.VisitMemberAccess(m);

                if (ClientTypeUtil.TypeOrElementTypeIsEntity(type))
                {
                    Type type2;
                    ResourceBinder.StripTo <Expression>(m.Expression, out type2);
                    this.box.AppendPropertyToPath(info, type2, this.context);
                    this.leafExpressionIsMemberAccess = false;
                }
                return(expression2);
            }
        internal override Expression VisitMethodCall(MethodCallExpression m)
        {
            Expression expressionBeforeNormalization = this.GetExpressionBeforeNormalization(m);

            if (expressionBeforeNormalization != m)
            {
                return(this.Visit(expressionBeforeNormalization));
            }
            if (this.pathBuilder.CurrentIsEntity)
            {
                if (m.Method.Name == "Select")
                {
                    return(this.RebindMethodCallForMemberSelect(m));
                }
                if (m.Method.Name == "ToList")
                {
                    return(this.RebindMethodCallForMemberToList(m));
                }
                return(base.VisitMethodCall(m));
            }
            if (ProjectionAnalyzer.IsMethodCallAllowedEntitySequence(m))
            {
                return(this.RebindMethodCallForNewSequence(m));
            }
            return(base.VisitMethodCall(m));
        }
Example #3
0
 internal override Expression VisitTypeIs(TypeBinaryExpression b)
 {
     if (ClientTypeUtil.TypeOrElementTypeIsEntity(b.Expression.Type) || ProjectionAnalyzer.IsCollectionProducingExpression(b.Expression))
     {
         throw new NotSupportedException(System.Data.Services.Client.Strings.ALinq_ExpressionNotSupportedInProjection(this.type, b.ToString()));
     }
     return(base.VisitTypeIs(b));
 }
Example #4
0
        private static void AnalyzeResourceExpression(LambdaExpression lambda, ResourceExpression resource)
        {
            PathBox pb = new PathBox();

            ProjectionAnalyzer.Analyze(lambda, pb);
            resource.Projection  = new ProjectionQueryOptionExpression(lambda.Body.Type, lambda, pb.ProjectionPaths.ToList());
            resource.ExpandPaths = pb.ExpandPaths.Union(resource.ExpandPaths, StringComparer.Ordinal).ToList();
        }
Example #5
0
 internal override Expression VisitMemberInit(MemberInitExpression init)
 {
     if (!ClientTypeUtil.TypeOrElementTypeIsEntity(init.Type))
     {
         throw new NotSupportedException(System.Data.Services.Client.Strings.ALinq_ExpressionNotSupportedInProjectionToEntity(this.type, init.ToString()));
     }
     ProjectionAnalyzer.Analyze(init, this.box, this.context);
     return(init);
 }
Example #6
0
        /// <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)
        {
            PathBox pb = new PathBox();

            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);
        }
Example #7
0
        private Expression RebindMethodCallForNewSequence(MethodCallExpression call)
        {
            Debug.Assert(call != null, "call != null");
            Debug.Assert(ProjectionAnalyzer.IsMethodCallAllowedEntitySequence(call), "ProjectionAnalyzer.IsMethodCallAllowedEntitySequence(call)");
            Debug.Assert(call.Object == null, "call.Object == null -- otherwise this isn't the supported Select or ToList methods");

            Expression result = null;

            if (call.Method.Name == "Select")
            {
                Debug.Assert(call.Arguments.Count == 2, "call.Arguments.Count == 2 -- otherwise this isn't the argument we expected");

                Expression           parameterSource = this.Visit(call.Arguments[0]);
                ExpressionAnnotation annotation;
                this.annotations.TryGetValue(parameterSource, out annotation);

                if (annotation != null)
                {
                    Expression selectorExpression = this.Visit(call.Arguments[1]);
                    Type       returnElementType  = call.Method.ReturnType.GetGenericArguments()[0];
                    result = CallMaterializer(
                        "ProjectionSelect",
                        this.materializerExpression,
                        this.pathBuilder.ParameterEntryInScope,
                        this.pathBuilder.ExpectedParamTypeInScope,
                        Expression.Constant(returnElementType, typeof(Type)),
                        Expression.Constant(annotation.Segment.StartPath, typeof(object)),
                        selectorExpression);
                    this.annotations.Add(result, annotation);
                    result = CallMaterializerWithType(
                        "EnumerateAsElementType",
                        new Type[] { returnElementType },
                        result);
                    this.annotations.Add(result, annotation);
                }
            }
            else
            {
                Debug.Assert(call.Method.Name == "ToList", "call.Method.Name == 'ToList'");

                Expression           source = this.Visit(call.Arguments[0]);
                ExpressionAnnotation annotation;
                if (this.annotations.TryGetValue(source, out annotation))
                {
                    result = this.TypedEnumerableToList(source, call.Type);
                    this.annotations.Add(result, annotation);
                }
            }

            if (result == null)
            {
                result = base.VisitMethodCall(call);
            }

            return(result);
        }
Example #8
0
            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.box, this.context);
                return(init);
            }
Example #9
0
 internal override Expression VisitMethodCall(MethodCallExpression m)
 {
     if (((m.Object != null) && ProjectionAnalyzer.IsDisallowedExpressionForMethodCall(m.Object, this.context.MaxProtocolVersion)) || m.Arguments.Any <Expression>(a => ProjectionAnalyzer.IsDisallowedExpressionForMethodCall(a, this.context.MaxProtocolVersion)))
     {
         throw new NotSupportedException(System.Data.Services.Client.Strings.ALinq_ExpressionNotSupportedInProjection(this.type, m.ToString()));
     }
     ProjectionAnalyzer.CheckChainedSequence(m, this.type);
     if (!ProjectionAnalyzer.IsMethodCallAllowedEntitySequence(m) && (((m.Object != null) ? ClientTypeUtil.TypeOrElementTypeIsEntity(m.Object.Type) : false) || m.Arguments.Any <Expression>(a => ClientTypeUtil.TypeOrElementTypeIsEntity(a.Type))))
     {
         throw new NotSupportedException(System.Data.Services.Client.Strings.ALinq_ExpressionNotSupportedInProjection(this.type, m.ToString()));
     }
     return(base.VisitMethodCall(m));
 }
Example #10
0
 internal override Expression VisitInvocation(InvocationExpression iv)
 {
     if ((ClientTypeUtil.TypeOrElementTypeIsEntity(iv.Expression.Type) || ProjectionAnalyzer.IsCollectionProducingExpression(iv.Expression)) || iv.Arguments.Any <Expression>(delegate(Expression a) {
         if (!ClientTypeUtil.TypeOrElementTypeIsEntity(a.Type))
         {
             return(ProjectionAnalyzer.IsCollectionProducingExpression(a));
         }
         return(true);
     }))
     {
         throw new NotSupportedException(System.Data.Services.Client.Strings.ALinq_ExpressionNotSupportedInProjection(this.type, iv.ToString()));
     }
     return(base.VisitInvocation(iv));
 }
Example #11
0
            internal override Expression VisitMethodCall(MethodCallExpression m)
            {
                if ((m.Object != null && IsDisallowedExpressionForMethodCall(m.Object)) ||
                    m.Arguments.Any(a => IsDisallowedExpressionForMethodCall(a)))
                {
                    throw new NotSupportedException(Strings.ALinq_ExpressionNotSupportedInProjection(this.type, m.ToString()));
                }

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

                    return(base.VisitMethodCall(m));
                }

                throw new NotSupportedException(Strings.ALinq_ExpressionNotSupportedInProjectionToEntity(this.type, m.ToString()));
            }
Example #12
0
        internal override Expression VisitMethodCall(MethodCallExpression m)
        {
            Debug.Assert(m != null, "m != null");

            Expression original = this.GetExpressionBeforeNormalization(m);

            if (original != m)
            {
                return(this.Visit(original));
            }

            Expression result;

            if (this.pathBuilder.CurrentIsEntity)
            {
                Debug.Assert(
                    ProjectionAnalyzer.IsMethodCallAllowedEntitySequence(m) || ResourceBinder.PatternRules.MatchReferenceEquals(m),
                    "ProjectionAnalyzer.IsMethodCallAllowedEntitySequence(m) || ResourceBinder.PatternRules.MatchReferenceEquals(m) -- otherwise ProjectionAnalyzer should have blocked this for entities");
                if (m.Method.Name == "Select")
                {
                    result = this.RebindMethodCallForMemberSelect(m);
                }
                else if (m.Method.Name == "ToList")
                {
                    result = this.RebindMethodCallForMemberToList(m);
                }
                else
                {
                    Debug.Assert(m.Method.Name == "ReferenceEquals", "We don't know how to handle this method, ProjectionAnalyzer updated?");
                    result = base.VisitMethodCall(m);
                }
            }
            else
            {
                if (ProjectionAnalyzer.IsMethodCallAllowedEntitySequence(m))
                {
                    result = this.RebindMethodCallForNewSequence(m);
                }
                else
                {
                    result = base.VisitMethodCall(m);
                }
            }

            return(result);
        }
Example #13
0
            internal override Expression VisitMethodCall(MethodCallExpression m)
            {
                if ((m.Object != null && IsDisallowedExpressionForMethodCall(m.Object)) ||
                    m.Arguments.Any(a => IsDisallowedExpressionForMethodCall(a)))
                {
                    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()));
            }
Example #14
0
            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()));
            }
Example #15
0
            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));
            }
Example #16
0
        internal override Expression VisitUnary(UnaryExpression u)
        {
            UnaryExpression expression = (UnaryExpression)base.VisitUnary(u);
            Expression      rewritten  = expression;

            this.RecordRewrite(u, rewritten);
            if ((expression.NodeType != ExpressionType.Convert) && (expression.NodeType != ExpressionType.TypeAs))
            {
                return(rewritten);
            }
            if (!expression.Type.IsAssignableFrom(expression.Operand.Type))
            {
                return(rewritten);
            }
            if ((PrimitiveType.IsKnownNullableType(expression.Operand.Type) || PrimitiveType.IsKnownNullableType(expression.Type)) && !(expression.Operand.Type == expression.Type))
            {
                return(rewritten);
            }
            if (ClientTypeUtil.TypeOrElementTypeIsEntity(expression.Operand.Type) && ProjectionAnalyzer.IsCollectionProducingExpression(expression.Operand))
            {
                return(rewritten);
            }
            return(expression.Operand);
        }
Example #17
0
 internal override Expression VisitLambda(LambdaExpression lambda)
 {
     ProjectionAnalyzer.Analyze(lambda, this.box);
     return(lambda);
 }
Example #18
0
        /// <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
        /// 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 (!ClientConvert.IsKnownNullableType(visited.Operand.Type) && !ClientConvert.IsKnownNullableType(visited.Type) || visited.Operand.Type == visited.Type)
                {
                    // x is not a collection of entity types
                    if (!(ClientType.CheckElementTypeIsEntity(visited.Operand.Type) && ProjectionAnalyzer.IsCollectionProducingExpression(visited.Operand)))
                    {
                        result = visited.Operand;
                    }
                }
            }

            return(result);
        }
Example #19
0
        internal override Expression VisitUnary(UnaryExpression u)
        {
            UnaryExpression visited = (UnaryExpression)base.VisitUnary(u);
            Expression      result  = visited;

            this.RecordRewrite(u, result);

            if ((visited.NodeType == ExpressionType.Convert || visited.NodeType == ExpressionType.TypeAs) && visited.Type.IsAssignableFrom(visited.Operand.Type))
            {
                if (!ClientConvert.IsKnownNullableType(visited.Operand.Type) && !ClientConvert.IsKnownNullableType(visited.Type) || visited.Operand.Type == visited.Type)
                {
                    if (!(ClientType.CheckElementTypeIsEntity(visited.Operand.Type) && ProjectionAnalyzer.IsCollectionProducingExpression(visited.Operand)))
                    {
                        result = visited.Operand;
                    }
                }
            }

            return(result);
        }
Example #20
0
 internal override Expression VisitMemberInit(MemberInitExpression init)
 {
     ProjectionAnalyzer.Analyze(init, this.box);
     return(init);
 }
Example #21
0
 internal override Expression VisitConditional(ConditionalExpression c)
 {
     ResourceBinder.PatternRules.MatchNullCheckResult result = ResourceBinder.PatternRules.MatchNullCheck(this.box.ParamExpressionInScope, c);
     if (result.Match)
     {
         this.Visit(result.AssignExpression);
         return(c);
     }
     if (((ClientTypeUtil.TypeOrElementTypeIsEntity(c.Test.Type) || ClientTypeUtil.TypeOrElementTypeIsEntity(c.IfTrue.Type)) || (ClientTypeUtil.TypeOrElementTypeIsEntity(c.IfFalse.Type) || ProjectionAnalyzer.IsCollectionProducingExpression(c.Test))) || (ProjectionAnalyzer.IsCollectionProducingExpression(c.IfTrue) || ProjectionAnalyzer.IsCollectionProducingExpression(c.IfFalse)))
     {
         throw new NotSupportedException(System.Data.Services.Client.Strings.ALinq_ExpressionNotSupportedInProjection(this.type, c.ToString()));
     }
     return(base.VisitConditional(c));
 }