Ejemplo n.º 1
0
        /// <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);
        }
Ejemplo n.º 2
0
        /// <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;
        }