/// <summary>
        /// Creates the <see cref="ODataEntry"/> to be written while writing this entity.
        /// </summary>
        /// <param name="selectExpandNode">The <see cref="SelectExpandNode"/> describing the response graph.</param>
        /// <param name="entityInstanceContext">The context for the entity instance being written.</param>
        /// <returns>The created <see cref="ODataEntry"/>.</returns>
        public virtual ODataEntry CreateEntry(SelectExpandNode selectExpandNode, EntityInstanceContext entityInstanceContext)
        {
            if (selectExpandNode == null)
            {
                throw Error.ArgumentNull("selectExpandNode");
            }
            if (entityInstanceContext == null)
            {
                throw Error.ArgumentNull("entityInstanceContext");
            }

            string typeName = entityInstanceContext.EntityType.FullName();

            ODataEntry entry = new ODataEntry
            {
                TypeName = typeName,
                Properties = CreateStructuralPropertyBag(selectExpandNode.SelectedStructuralProperties, entityInstanceContext),
            };

            // Try to add the dynamic properties if the entity type is open.
            if ((entityInstanceContext.EntityType.IsOpen && selectExpandNode.SelectAllDynamicProperties) ||
                (entityInstanceContext.EntityType.IsOpen && selectExpandNode.SelectedDynamicProperties.Any()))
            {
                IEdmTypeReference entityTypeReference =
                    entityInstanceContext.EntityType.ToEdmTypeReference(isNullable: false);
                List<ODataProperty> dynamicProperties = AppendDynamicProperties(entityInstanceContext.EdmObject,
                    (IEdmStructuredTypeReference)entityTypeReference,
                    entityInstanceContext.SerializerContext,
                    entry.Properties.ToList(),
                    selectExpandNode.SelectedDynamicProperties.ToArray());

                if (dynamicProperties != null)
                {
                    entry.Properties = entry.Properties.Concat(dynamicProperties);
                }
            }

            IEnumerable<ODataAction> actions = CreateODataActions(selectExpandNode.SelectedActions, entityInstanceContext);
            foreach (ODataAction action in actions)
            {
                entry.AddAction(action);
            }

            IEdmEntityType pathType = GetODataPathType(entityInstanceContext.SerializerContext);
            AddTypeNameAnnotationAsNeeded(entry, pathType, entityInstanceContext.SerializerContext.MetadataLevel);

            if (entityInstanceContext.NavigationSource != null)
            {
                if (!(entityInstanceContext.NavigationSource is IEdmContainedEntitySet))
                {
                    IEdmModel model = entityInstanceContext.SerializerContext.Model;
                    NavigationSourceLinkBuilderAnnotation linkBuilder = model.GetNavigationSourceLinkBuilder(entityInstanceContext.NavigationSource);
                    EntitySelfLinks selfLinks = linkBuilder.BuildEntitySelfLinks(entityInstanceContext, entityInstanceContext.SerializerContext.MetadataLevel);

                    if (selfLinks.IdLink != null)
                    {
                        entry.Id = selfLinks.IdLink;
                    }

                    if (selfLinks.ReadLink != null)
                    {
                        entry.ReadLink = selfLinks.ReadLink;
                    }

                    if (selfLinks.EditLink != null)
                    {
                        entry.EditLink = selfLinks.EditLink;
                    }
                }

                string etag = CreateETag(entityInstanceContext);
                if (etag != null)
                {
                    entry.ETag = etag;
                }
            }

            return entry;
        }
Ejemplo n.º 2
0
        public void SelectProperties_OnSubPropertyWithTypeCastFromComplex_SelectsExpectedProperties()
        {
            // Arrange
            EdmComplexType subComplexType = new EdmComplexType("NS", "CnAddress", _model.Address);

            subComplexType.AddStructuralProperty("SubAddressProperty", EdmPrimitiveTypeKind.String);
            subComplexType.AddUnidirectionalNavigation(new EdmNavigationPropertyInfo
            {
                Name = "CnAddressOrderNav",
                TargetMultiplicity = EdmMultiplicity.One,
                Target             = _model.Order
            });
            _model.Model.AddElement(subComplexType);

            string select = "Address/NS.CnAddress/SubAddressProperty";
            string expand = "Address/NS.CnAddress/CnAddressOrderNav";

            SelectExpandClause selectExpandClause = ParseSelectExpand(select, expand);

            // Act
            SelectExpandNode selectExpandNode = new SelectExpandNode(selectExpandClause, _model.Customer, _model.Model);

            // Assert: Top Level
            Assert.Null(selectExpandNode.SelectedStructuralProperties);
            Assert.Null(selectExpandNode.SelectedNavigationProperties);
            Assert.Null(selectExpandNode.ExpandedProperties); // Not expanded at first level

            Assert.NotNull(selectExpandNode.SelectedComplexProperties);
            var firstLevelSelected = Assert.Single(selectExpandNode.SelectedComplexProperties);

            Assert.Equal("Address", firstLevelSelected.Key.Name);

            Assert.NotNull(firstLevelSelected.Value);
            Assert.NotNull(firstLevelSelected.Value.SelectAndExpand);

            // Assert: Second Level
            {
                // use the base type to test
                SelectExpandNode subSelectExpandNode = new SelectExpandNode(firstLevelSelected.Value.SelectAndExpand, _model.Address, _model.Model);
                Assert.Null(subSelectExpandNode.SelectedStructuralProperties);
                Assert.Null(subSelectExpandNode.SelectedComplexProperties);
                Assert.Null(subSelectExpandNode.ExpandedProperties);
                Assert.Null(subSelectExpandNode.SelectedNavigationProperties);
            }
            {
                // use the sub type to test
                SelectExpandNode subSelectExpandNode = new SelectExpandNode(firstLevelSelected.Value.SelectAndExpand, subComplexType, _model.Model);
                Assert.Null(subSelectExpandNode.SelectedComplexProperties);
                Assert.NotNull(subSelectExpandNode.SelectedStructuralProperties);
                Assert.Equal("SubAddressProperty", Assert.Single(subSelectExpandNode.SelectedStructuralProperties).Name);

                Assert.NotNull(subSelectExpandNode.ExpandedProperties);
                var expandedProperty = Assert.Single(subSelectExpandNode.ExpandedProperties);
                Assert.Equal("CnAddressOrderNav", expandedProperty.Key.Name);

                Assert.NotNull(expandedProperty.Value);
                Assert.NotNull(expandedProperty.Value.SelectAndExpand);
                Assert.True(expandedProperty.Value.SelectAndExpand.AllSelected);
                Assert.Empty(expandedProperty.Value.SelectAndExpand.SelectedItems);
            }
        }
        /// <summary>
        /// Creates the <see cref="SelectExpandNode"/> that describes the set of properties and actions to select and expand while writing this entity.
        /// </summary>
        /// <param name="entityInstanceContext">Contains the entity instance being written and the context.</param>
        /// <returns>
        /// The <see cref="SelectExpandNode"/> that describes the set of properties and actions to select and expand while writing this entity.
        /// </returns>
        public virtual SelectExpandNode CreateSelectExpandNode(EntityInstanceContext entityInstanceContext)
        {
            if (entityInstanceContext == null)
            {
                throw Error.ArgumentNull("entityInstanceContext");
            }

            ODataSerializerContext writeContext = entityInstanceContext.SerializerContext;
            IEdmEntityType entityType = entityInstanceContext.EntityType;

            object selectExpandNode;
            Tuple<SelectExpandClause, IEdmEntityType> key = Tuple.Create(writeContext.SelectExpandClause, entityType);
            if (!writeContext.Items.TryGetValue(key, out selectExpandNode))
            {
                // cache the selectExpandNode so that if we are writing a feed we don't have to construct it again.
                selectExpandNode = new SelectExpandNode(writeContext.SelectExpandClause, entityType, writeContext.Model);
                writeContext.Items[key] = selectExpandNode;
            }
            return selectExpandNode as SelectExpandNode;
        }