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