/// <summary>Builds the Uri for the expression passed in.</summary>
        /// <param name="e">The expression to translate into a Uri</param>
        /// <returns>Query components</returns>
        internal QueryComponents Translate(Expression e)
        {
            Uri     uri;
            Version version;
            bool    addTrailingParens = false;
            Dictionary <Expression, Expression> normalizerRewrites = null;

            // short cut analysis if just a resource set or singleton resource.
            // note - to be backwards compatible with V1, will only append trailing () for queries
            // that include more then just a resource set.
            if (!(e is QueryableResourceExpression))
            {
                normalizerRewrites = new Dictionary <Expression, Expression>(ReferenceEqualityComparer <Expression> .Instance);
                e = Evaluator.PartialEval(e);
                e = ExpressionNormalizer.Normalize(e, normalizerRewrites);
                e = ResourceBinder.Bind(e, this.Context);
                addTrailingParens = true;
            }

            UriWriter.Translate(this.Context, addTrailingParens, e, out uri, out version);
            ResourceExpression re            = e as ResourceExpression;
            Type             lastSegmentType = re.Projection == null ? re.ResourceType : re.Projection.Selector.Parameters[0].Type;
            LambdaExpression selector        = re.Projection == null ? null : re.Projection.Selector;

            return(new QueryComponents(uri, version, lastSegmentType, selector, normalizerRewrites));
        }
Example #2
0
        /// <summary>
        /// QueryableResourceExpression visit method.
        /// </summary>
        /// <param name="rse">QueryableResourceExpression expression to visit</param>
        /// <returns>Visited QueryableResourceExpression expression</returns>
        internal override Expression VisitQueryableResourceExpression(QueryableResourceExpression rse)
        {
            if ((ResourceExpressionType)rse.NodeType == ResourceExpressionType.ResourceNavigationProperty)
            {
                if (rse.IsOperationInvocation && !(rse.Source is QueryableResourceExpression))
                {
                    var normalizerRewrites = new Dictionary <Expression, Expression>(ReferenceEqualityComparer <Expression> .Instance);
                    var e = Evaluator.PartialEval(rse.Source);
                    e = ExpressionNormalizer.Normalize(e, normalizerRewrites);
                    e = ResourceBinder.Bind(e, this.context);
                    this.Visit(e);
                }
                else
                {
                    this.Visit(rse.Source);
                }

                this.uriBuilder.Append(UriHelper.FORWARDSLASH).Append(this.ExpressionToString(rse.MemberExpression, /*inPath*/ true));
            }
            else if (rse.MemberExpression != null)
            {
                // this is a resource set expression
                // we should be at the very beginning of
                // the URI
                Debug.Assert(this.uriBuilder.Length == 0, "The builder is not empty while we are adding a resourceset");
                string entitySetName = (String)((ConstantExpression)rse.MemberExpression).Value;
                this.uriBuilder.Append(this.context.BaseUriResolver.GetEntitySetUri(entitySetName));
            }
            else
            {
                this.uriBuilder.Append(this.context.BaseUriResolver.BaseUriOrNull);
            }

            WebUtil.RaiseVersion(ref this.uriVersion, rse.UriVersion);

            if (rse.ResourceTypeAs != null)
            {
                this.uriBuilder.Append(UriHelper.FORWARDSLASH);
                UriHelper.AppendTypeSegment(this.uriBuilder, rse.ResourceTypeAs, this.context, /*inPath*/ true, ref this.uriVersion);
            }

            if (rse.KeyPredicateConjuncts.Count > 0)
            {
                this.context.UrlKeyDelimiter.AppendKeyExpression(rse.GetKeyProperties(), kvp => ClientTypeUtil.GetServerDefinedName(kvp.Key), kvp => kvp.Value.Value, this.uriBuilder);
            }

            if (rse.IsOperationInvocation)
            {
                this.VisitOperationInvocation(rse);
            }

            if (rse.CountOption == CountOption.CountSegment)
            {
                // append $count segment: /$count
                this.uriBuilder.Append(UriHelper.FORWARDSLASH).Append(UriHelper.DOLLARSIGN).Append(UriHelper.COUNT);
            }

            this.VisitQueryOptions(rse);
            return(rse);
        }
        /// <summary>
        /// Applies normalization rewrites to the specified
        /// <paramref name="expression"/>, recording them in the
        /// <paramref name="rewrites"/> dictionary.
        /// </summary>
        /// <param name="expression">Expression to normalize.</param>
        /// <param name="rewrites">Dictionary in which to record rewrites.</param>
        /// <returns>The normalized expression.</returns>
        internal static Expression Normalize(Expression expression, Dictionary <Expression, Expression> rewrites)
        {
            Debug.Assert(expression != null, "expression != null");
            Debug.Assert(rewrites != null, "rewrites != null");

            ExpressionNormalizer normalizer = new ExpressionNormalizer(rewrites);
            Expression           result     = normalizer.Visit(expression);

            return(result);
        }