/// <summary> /// Creates an instance of <see cref="ExpandSegment"/> based on the metadata in the given <see cref="ExpandedNavigationSelectItem"/>. /// </summary> /// <param name="expandItem">The metadata-bound expand segment to create the <see cref="ExpandSegment"/> from.</param> /// <param name="currentResourceType">The current resource type.</param> /// <returns>The created <see cref="ExpandSegment"/>.</returns> private ExpandSegment CreateExpandSegment(ExpandedNavigationSelectItem expandItem, ResourceType currentResourceType) { Debug.Assert(expandItem != null, "expandItem != null"); Debug.Assert(currentResourceType != null, "currentResourceType != null"); // pull the Resource* instances from annotations on the IEdm* instances. IEdmNavigationProperty navigationProperty = ((NavigationPropertySegment)expandItem.PathToNavigationProperty.LastSegment).NavigationProperty; ResourceProperty property = ((IResourcePropertyBasedEdmProperty)navigationProperty).ResourceProperty; Debug.Assert(property != null, "property != null"); ResourceSetWrapper targetResourceSet = ((IResourceSetBasedEdmEntitySet)expandItem.NavigationSource).ResourceSet; Debug.Assert(targetResourceSet != null, "targetResourceSet != null"); // Further scope the type based on type segments in the path. currentResourceType = this.GetTargetResourceTypeFromTypeSegments(expandItem.PathToNavigationProperty, currentResourceType); Debug.Assert(currentResourceType != null, "currentResourceType != null"); // The expanded resource type may require higher response version. Update version of the response accordingly // // Note the response DSV is payload specific and since for GET we won't know what DSV the instances to be // serialized will require until serialization time which happens after the headers are written, // the best we can do is to determine this at the set level. this.description.UpdateVersion(targetResourceSet, this.service); bool singleResult = property.Kind == ResourcePropertyKind.ResourceReference; DataServiceConfiguration.CheckResourceRightsForRead(targetResourceSet, singleResult); Expression filter = DataServiceConfiguration.ComposeQueryInterceptors(this.service.Instance, targetResourceSet); if (targetResourceSet.PageSize != 0 && !singleResult && !this.IsCustomPaged) { OrderingInfo internalOrderingInfo = new OrderingInfo(true); ParameterExpression p = Expression.Parameter(targetResourceSet.ResourceType.InstanceType, "p"); foreach (var keyProp in targetResourceSet.GetKeyPropertiesForOrderBy()) { Expression e; if (keyProp.CanReflectOnInstanceTypeProperty) { e = Expression.Property(p, targetResourceSet.ResourceType.GetPropertyInfo(keyProp)); } else { // object LateBoundMethods.GetValue(object, ResourceProperty) e = Expression.Call( null, /*instance*/ DataServiceProviderMethods.GetValueMethodInfo, p, Expression.Constant(keyProp)); e = Expression.Convert(e, keyProp.Type); } internalOrderingInfo.Add(new OrderingExpression(Expression.Lambda(e, p), true)); } return new ExpandSegment(property.Name, filter, targetResourceSet.PageSize, targetResourceSet, currentResourceType, property, internalOrderingInfo); } if (!singleResult && this.IsCustomPaged) { // Expansion of collection could result in custom paging provider giving next link, so we need to set the null continuation token. this.CheckAndApplyCustomPaging(null); } return new ExpandSegment(property.Name, filter, this.service.Configuration.MaxResultsPerCollection, targetResourceSet, currentResourceType, property, null); }
/// <summary> /// Updates the topLevelOrderingInfo member with the new collection of expressions that /// dereference the ExpandedElement property on the top level wrapper object /// </summary> /// <param name="resultWrapperType">Type of top level wrapper object</param> private void UpdateOrderingInfoWithSkipTokenWrapper(Type resultWrapperType) { OrderingInfo newOrderingInfo = new OrderingInfo(true); ParameterExpression wrapperParameter = Expression.Parameter(resultWrapperType, "w"); foreach (var ordering in this.topLevelOrderingInfo.OrderingExpressions) { LambdaExpression oldExpression = (LambdaExpression)ordering.Expression; Expression newOrdering = ParameterReplacerVisitor.Replace( oldExpression.Body, oldExpression.Parameters[0], Expression.MakeMemberAccess(wrapperParameter, resultWrapperType.GetProperty("ExpandedElement"))); newOrderingInfo.Add(new OrderingExpression(Expression.Lambda(newOrdering, wrapperParameter), ordering.IsAscending)); } this.topLevelOrderingInfo = newOrderingInfo; }