Example #1
0
        /// <summary>
        /// Serializes an UnaryExpression to a string
        /// </summary>
        /// <param name="u">Expression to serialize</param>
        /// <returns>UnaryExpression</returns>
        internal override Expression VisitUnary(UnaryExpression u)
        {
            switch (u.NodeType)
            {
            case ExpressionType.Not:
                this.builder.Append(UriHelper.NOT);
                this.builder.Append(UriHelper.SPACE);
                this.VisitOperand(u.Operand);
                break;

            case ExpressionType.Negate:
            case ExpressionType.NegateChecked:
                this.builder.Append(UriHelper.SPACE);
                this.builder.Append(UriHelper.NEGATE);
                this.VisitOperand(u.Operand);
                break;

            case ExpressionType.Convert:
            case ExpressionType.ConvertChecked:
                if (u.Type != typeof(object))
                {
                    this.builder.Append(UriHelper.CAST);
                    this.builder.Append(UriHelper.LEFTPAREN);
                    if (!this.IsImplicitInputReference(u.Operand))
                    {
                        this.Visit(u.Operand);
                        this.builder.Append(UriHelper.COMMA);
                    }

                    this.builder.Append(UriHelper.QUOTE);
                    this.builder.Append(UriHelper.GetTypeNameForUri(u.Type, this.context));
                    this.builder.Append(UriHelper.QUOTE);
                    this.builder.Append(UriHelper.RIGHTPAREN);
                }
                else
                {
                    if (!this.IsImplicitInputReference(u.Operand))
                    {
                        this.Visit(u.Operand);
                    }
                }

                break;

            case ExpressionType.TypeAs:
                if (u.Operand.NodeType == ExpressionType.TypeAs)
                {
                    throw new NotSupportedException(Strings.ALinq_CannotUseTypeFiltersMultipleTimes);
                }

                this.Visit(u.Operand);

                if (!this.IsImplicitInputReference(u.Operand))
                {
                    // InputReferenceExpressions aren't emitted, so no leading slash is required
                    this.builder.Append(UriHelper.FORWARDSLASH);
                }

                UriHelper.AppendTypeSegment(this.builder, u.Type, this.context, this.inPath, ref this.uriVersion);

                break;

            case ExpressionType.UnaryPlus:
                // no-op always ignore.
                break;

            default:
                this.cantTranslateExpression = true;
                break;
            }

            return(u);
        }
Example #2
0
        /// <summary>
        /// MethodCallExpression visit method
        /// </summary>
        /// <param name="m">The MethodCallExpression expression to visit</param>
        /// <returns>The visited MethodCallExpression expression </returns>
        internal override Expression VisitMethodCall(MethodCallExpression m)
        {
            string methodName;

            if (TypeSystem.TryGetQueryOptionMethod(m.Method, out methodName))
            {
                this.builder.Append(methodName);
                this.builder.Append(UriHelper.LEFTPAREN);

                // There is a single function, 'substringof', which reorders its argument with
                // respect to the CLR method. Thus handling it as a special case rather than
                // using a more general argument reordering mechanism.
                if (methodName == "substringof")
                {
                    Debug.Assert(m.Method.Name == "Contains", "m.Method.Name == 'Contains'");
                    Debug.Assert(m.Object != null, "m.Object != null");
                    Debug.Assert(m.Arguments.Count == 1, "m.Arguments.Count == 1");
                    this.Visit(m.Arguments[0]);
                    this.builder.Append(UriHelper.COMMA);
                    this.Visit(m.Object);
                }
                else
                {
                    if (m.Object != null)
                    {
                        this.Visit(m.Object);
                    }

                    if (m.Arguments.Count > 0)
                    {
                        if (m.Object != null)
                        {
                            this.builder.Append(UriHelper.COMMA);
                        }

                        for (int ii = 0; ii < m.Arguments.Count; ii++)
                        {
                            this.Visit(m.Arguments[ii]);
                            if (ii < m.Arguments.Count - 1)
                            {
                                this.builder.Append(UriHelper.COMMA);
                            }
                        }
                    }
                }

                this.builder.Append(UriHelper.RIGHTPAREN);
            }
            else
            {
                SequenceMethod sequenceMethod;
                if (ReflectionUtil.TryIdentifySequenceMethod(m.Method, out sequenceMethod))
                {
                    if (ReflectionUtil.IsAnyAllMethod(sequenceMethod))
                    {
                        // Raise the uriVersion each time we write any or all methods to the uri.
                        WebUtil.RaiseVersion(ref this.uriVersion, Util.DataServiceVersion3);

                        this.Visit(m.Arguments[0]);
                        this.builder.Append(UriHelper.FORWARDSLASH);
                        if (sequenceMethod == SequenceMethod.All)
                        {
                            this.builder.Append(XmlConstants.AllMethodName);
                        }
                        else
                        {
                            this.builder.Append(XmlConstants.AnyMethodName);
                        }

                        this.builder.Append(UriHelper.LEFTPAREN);
                        if (sequenceMethod != SequenceMethod.Any)
                        {
                            // SequenceMethod.Any represents Enumerable.Any(), which has only source argument
                            // AnyPredicate and All has a second parameter which is the predicate lambda.
                            Debug.Assert(m.Arguments.Count() == 2, "m.Arguments.Count() == 2");
                            LambdaExpression le            = (LambdaExpression)m.Arguments[1];
                            string           rangeVariable = le.Parameters[0].Name;
                            this.builder.Append(rangeVariable);
                            this.builder.Append(UriHelper.COLON);
                            this.scopeCount++;
                            this.Visit(le.Body);
                            this.scopeCount--;
                        }

                        this.builder.Append(UriHelper.RIGHTPAREN);
                        return(m);
                    }
                    else if (sequenceMethod == SequenceMethod.OfType && this.parent != null)
                    {
                        // check to see if this is an OfType filter for Any or All.
                        // e.g. ctx.CreateQuery<Movie>("Movies").Where(m=>m.Actors.OfType<MegaStar>().Any())
                        //      which translates to /Movies()?$filter=Actors/MegaStar/any()
                        MethodCallExpression mce = this.parent as MethodCallExpression;
                        if (mce != null &&
                            ReflectionUtil.TryIdentifySequenceMethod(mce.Method, out sequenceMethod) &&
                            ReflectionUtil.IsAnyAllMethod(sequenceMethod))
                        {
                            Type filteredType = mce.Method.GetGenericArguments().SingleOrDefault();
                            if (ClientTypeUtil.TypeOrElementTypeIsEntity(filteredType))
                            {
                                this.Visit(m.Arguments[0]);
                                this.builder.Append(UriHelper.FORWARDSLASH);

                                UriHelper.AppendTypeSegment(this.builder, filteredType, this.context, this.inPath, ref this.uriVersion);

                                return(m);
                            }
                        }
                    }
                }

                this.cantTranslateExpression = true;
            }

            return(m);
        }