internal static void ApplyProperty(ODataProperty property, IEdmStructuredTypeReference resourceType, object resource,
            ODataDeserializerProvider deserializerProvider, ODataDeserializerContext readContext, AssembliesResolver assembliesResolver)
        {
            IEdmProperty edmProperty = resourceType.FindProperty(property.Name);

            bool isDynamicProperty = false;
            string propertyName = property.Name;
            if (edmProperty != null)
            {
                propertyName = EdmLibHelpers.GetClrPropertyName(edmProperty, readContext.Model);
            }
            else
            {
                IEdmStructuredType structuredType = resourceType.StructuredDefinition();
                isDynamicProperty = structuredType != null && structuredType.IsOpen;
            }

            // dynamic properties have null values
            IEdmTypeReference propertyType = edmProperty != null ? edmProperty.Type : null;

            EdmTypeKind propertyKind;
            object value = ConvertValue(property.Value, ref propertyType, deserializerProvider, readContext,
                out propertyKind);

            if (isDynamicProperty)
            {
                SetDynamicProperty(resource, resourceType, propertyKind, propertyName, value, propertyType,
                    readContext, assembliesResolver);
            }
            else
            {
                SetDeclaredProperty(resource, propertyKind, propertyName, value, edmProperty, readContext, assembliesResolver);
            }
        }
 internal static void SetDynamicProperty(object resource, IEdmStructuredTypeReference resourceType,
     EdmTypeKind propertyKind, string propertyName, object propertyValue, IEdmTypeReference propertyType,
     ODataDeserializerContext readContext, AssembliesResolver assembliesResolver)
 {  
     if (propertyKind == EdmTypeKind.Collection && propertyValue.GetType() != typeof(EdmComplexObjectCollection)
         && propertyValue.GetType() != typeof(EdmEnumObjectCollection))
     {
         SetDynamicCollectionProperty(resource, propertyName, propertyValue, propertyType.AsCollection(),
             resourceType.StructuredDefinition(), readContext, assembliesResolver);
     }
     else
     {
         SetDynamicProperty(resource, propertyName, propertyValue, resourceType.StructuredDefinition(),
             readContext);
     }
 }
        internal static void SetDeclaredProperty(object resource, EdmTypeKind propertyKind, string propertyName,
            object propertyValue, IEdmProperty edmProperty, ODataDeserializerContext readContext, AssembliesResolver assembliesResolver)
        {
            if (propertyKind == EdmTypeKind.Collection)
            {
                SetCollectionProperty(resource, edmProperty, propertyValue, propertyName, assembliesResolver);
            }
            else
            {
                if (!readContext.IsUntyped)
                {
                    if (propertyKind == EdmTypeKind.Primitive)
                    {
                        propertyValue = EdmPrimitiveHelpers.ConvertPrimitiveValue(propertyValue,
                            GetPropertyType(resource, propertyName));
                    }
                }

                SetProperty(resource, propertyName, propertyValue);
            }
        }
        internal static void SetDynamicCollectionProperty(object resource, string propertyName, object value,
            IEdmCollectionTypeReference edmPropertyType, IEdmStructuredType structuredType,
            ODataDeserializerContext readContext, AssembliesResolver assembliesResolver)
        {
            Contract.Assert(value != null);
            Contract.Assert(readContext != null);
            Contract.Assert(readContext.Model != null);

            IEnumerable collection = value as IEnumerable;
            Contract.Assert(collection != null);

            Type resourceType = resource.GetType();
            Type elementType = EdmLibHelpers.GetClrType(edmPropertyType.ElementType(), readContext.Model, assembliesResolver);
            Type propertyType = typeof(ICollection<>).MakeGenericType(elementType);
            IEnumerable newCollection;
            if (CollectionDeserializationHelpers.TryCreateInstance(propertyType, edmPropertyType, elementType,
                out newCollection))
            {
                collection.AddToCollection(newCollection, elementType, resourceType, propertyName, propertyType, assembliesResolver);
                SetDynamicProperty(resource, propertyName, newCollection, structuredType, readContext);
            }
        }
        /// <inheritdoc />
        public sealed override object ReadInline(object item, IEdmTypeReference edmType, ODataDeserializerContext readContext)
        {
            if (item == null)
            {
                return(null);
            }

            if (edmType == null)
            {
                throw Error.ArgumentNull("edmType");
            }

            if (!edmType.IsCollection() || !edmType.AsCollection().ElementType().IsStructured())
            {
                throw Error.Argument("edmType", "TODO:" /* SRResources.TypeMustBeResourceSet, edmType.ToTraceString()*/);
            }

            ODataResourceSetWrapper resourceSet = item as ODataResourceSetWrapper;

            if (resourceSet == null)
            {
                throw Error.Argument("item", SRResources.ArgumentMustBeOfType, typeof(ODataResourceSetWrapper).Name);
            }

            // Recursion guard to avoid stack overflows
            RuntimeHelpers.EnsureSufficientExecutionStack();

            IEdmStructuredTypeReference elementType = edmType.AsCollection().ElementType().AsStructured();

            IEnumerable result = ReadResourceSet(resourceSet, elementType, readContext);

            if (result != null && elementType.IsComplex())
            {
                if (readContext.IsUntyped)
                {
                    EdmComplexObjectCollection complexCollection = new EdmComplexObjectCollection(edmType.AsCollection());
                    foreach (EdmComplexObject complexObject in result)
                    {
                        complexCollection.Add(complexObject);
                    }
                    return(complexCollection);
                }
                else
                {
                    Type        elementClrType = EdmLibHelpers.GetClrType(elementType, readContext.Model);
                    IEnumerable castedResult   =
                        CastMethodInfo.MakeGenericMethod(elementClrType).Invoke(null, new object[] { result }) as
                        IEnumerable;
                    return(castedResult);
                }
            }
            else
            {
                return(result);
            }
        }
        /// <summary>
        /// Deserializes the nested property from <paramref name="resourceInfoWrapper"/> into <paramref name="resource"/>.
        /// </summary>
        /// <param name="resource">The object into which the nested property should be read.</param>
        /// <param name="resourceInfoWrapper">The nested resource info.</param>
        /// <param name="structuredType">The type of the resource.</param>
        /// <param name="readContext">The deserializer context.</param>
        public virtual void ApplyNestedProperty(object resource, ODataNestedResourceInfoWrapper resourceInfoWrapper,
                                                IEdmStructuredTypeReference structuredType, ODataDeserializerContext readContext)
        {
            if (resource == null)
            {
                throw new ArgumentNullException(nameof(resource));
            }

            if (resourceInfoWrapper == null)
            {
                throw new ArgumentNullException(nameof(resourceInfoWrapper));
            }

            IEdmProperty edmProperty = structuredType.FindProperty(resourceInfoWrapper.NestedResourceInfo.Name);

            if (edmProperty == null)
            {
                if (!structuredType.IsOpen())
                {
                    throw new ODataException(
                              Error.Format(SRResources.NestedPropertyNotfound, resourceInfoWrapper.NestedResourceInfo.Name,
                                           structuredType.FullName()));
                }
            }

            foreach (ODataItemBase childItem in resourceInfoWrapper.NestedItems)
            {
                // it maybe null.
                if (childItem == null)
                {
                    if (edmProperty == null)
                    {
                        // for the dynamic, OData.net has a bug. see https://github.com/OData/odata.net/issues/977
                        ApplyDynamicResourceInNestedProperty(resourceInfoWrapper.NestedResourceInfo.Name, resource,
                                                             structuredType, null, readContext);
                    }
                    else
                    {
                        ApplyResourceInNestedProperty(edmProperty, resource, null, readContext);
                    }
                }

                ODataEntityReferenceLinkBase entityReferenceLink = childItem as ODataEntityReferenceLinkBase;
                if (entityReferenceLink != null)
                {
                    // ignore entity reference links.
                    continue;
                }

                ODataResourceSetWrapper resourceSetWrapper = childItem as ODataResourceSetWrapper;
                if (resourceSetWrapper != null)
                {
                    if (edmProperty == null)
                    {
                        ApplyDynamicResourceSetInNestedProperty(resourceInfoWrapper.NestedResourceInfo.Name,
                                                                resource, structuredType, resourceSetWrapper, readContext);
                    }
                    else
                    {
                        ApplyResourceSetInNestedProperty(edmProperty, resource, resourceSetWrapper, readContext);
                    }

                    continue;
                }

                // It must be resource by now.
                ODataResourceWrapper resourceWrapper = (ODataResourceWrapper)childItem;
                if (resourceWrapper != null)
                {
                    if (edmProperty == null)
                    {
                        ApplyDynamicResourceInNestedProperty(resourceInfoWrapper.NestedResourceInfo.Name, resource,
                                                             structuredType, resourceWrapper, readContext);
                    }
                    else
                    {
                        ApplyResourceInNestedProperty(edmProperty, resource, resourceWrapper, readContext);
                    }
                }
            }
        }
        /// <summary>
        /// Deserializes the structural properties from <paramref name="resourceWrapper"/> into <paramref name="resource"/>.
        /// </summary>
        /// <param name="resource">The object into which the structural properties should be read.</param>
        /// <param name="resourceWrapper">The resource object containing the structural properties.</param>
        /// <param name="structuredType">The type of the resource.</param>
        /// <param name="readContext">The deserializer context.</param>
        public virtual void ApplyStructuralProperties(object resource, ODataResourceWrapper resourceWrapper,
                                                      IEdmStructuredTypeReference structuredType, ODataDeserializerContext readContext)
        {
            if (resourceWrapper == null)
            {
                throw new ArgumentNullException(nameof(resourceWrapper));
            }

            foreach (ODataProperty property in resourceWrapper.Resource.Properties)
            {
                ApplyStructuralProperty(resource, property, structuredType, readContext);
            }
        }
Example #8
0
        /// <inheritdoc />
        public sealed override object ReadInline(object item, IEdmTypeReference edmType, ODataDeserializerContext readContext)
        {
            if (edmType == null)
            {
                throw new ArgumentNullException(nameof(edmType));
            }

            if (edmType.IsComplex() && item == null)
            {
                return(null);
            }

            if (item == null)
            {
                throw new ArgumentNullException(nameof(item));
            }

            if (!edmType.IsStructured())
            {
                throw Error.Argument("edmType", SRResources.ArgumentMustBeOfType, "Entity or Complex");
            }

            ODataResourceWrapper resourceWrapper = item as ODataResourceWrapper;

            if (resourceWrapper == null)
            {
                throw Error.Argument("item", SRResources.ArgumentMustBeOfType, typeof(ODataResource).Name);
            }

            // Recursion guard to avoid stack overflows
            RuntimeHelpers.EnsureSufficientExecutionStack();

            resourceWrapper = UpdateResourceWrapper(resourceWrapper, readContext);

            return(ReadResource(resourceWrapper, edmType.AsStructured(), readContext));
        }
        /// <summary>
        /// Creates a new instance of the backing CLR object for the given resource type.
        /// </summary>
        /// <param name="structuredType">The EDM type of the resource to create.</param>
        /// <param name="readContext">The deserializer context.</param>
        /// <returns>The created CLR object.</returns>
        public virtual object CreateResourceInstance(IEdmStructuredTypeReference structuredType, ODataDeserializerContext readContext)
        {
            if (structuredType == null)
            {
                throw new ArgumentNullException(nameof(structuredType));
            }

            if (readContext == null)
            {
                throw new ArgumentNullException(nameof(readContext));
            }

            IEdmModel model = readContext.Model;

            if (model == null)
            {
                throw Error.Argument("readContext", SRResources.ModelMissingFromReadContext);
            }

            if (readContext.IsUntyped)
            {
                if (structuredType.IsEntity())
                {
                    return(new EdmEntityObject(structuredType.AsEntity()));
                }

                return(new EdmComplexObject(structuredType.AsComplex()));
            }
            else
            {
                Type clrType = model.GetClrType(structuredType);
                if (clrType == null)
                {
                    throw new ODataException(
                              Error.Format(SRResources.MappingDoesNotContainResourceType, structuredType.FullName()));
                }

                if (readContext.IsDeltaOfT)
                {
                    IEnumerable <string> structuralProperties = structuredType.StructuralProperties()
                                                                .Select(edmProperty => model.GetClrPropertyName(edmProperty));

                    if (structuredType.IsOpen())
                    {
                        PropertyInfo dynamicDictionaryPropertyInfo = model.GetDynamicPropertyDictionary(
                            structuredType.StructuredDefinition());

                        return(Activator.CreateInstance(readContext.ResourceType, clrType, structuralProperties,
                                                        dynamicDictionaryPropertyInfo));
                    }
                    else
                    {
                        return(Activator.CreateInstance(readContext.ResourceType, clrType, structuralProperties));
                    }
                }
                else
                {
                    return(Activator.CreateInstance(clrType));
                }
            }
        }
        /// <summary>
        /// Deserializes the given <paramref name="resourceSet"/> under the given <paramref name="readContext"/>.
        /// </summary>
        /// <param name="resourceSet">The resource set to deserialize.</param>
        /// <param name="readContext">The deserializer context.</param>
        /// <param name="elementType">The element type of the resource set being read.</param>
        /// <returns>The deserialized resource set object.</returns>
        public virtual IEnumerable ReadResourceSet(ODataResourceSetWrapper resourceSet, IEdmStructuredTypeReference elementType, ODataDeserializerContext readContext)
        {
            ODataEdmTypeDeserializer deserializer = DeserializerProvider.GetEdmTypeDeserializer(elementType);

            if (deserializer == null)
            {
                throw new SerializationException(
                          Error.Format(SRResources.TypeCannotBeDeserialized, elementType.FullName(), typeof(ODataInputFormatter).Name));
            }

            foreach (ODataResourceWrapper resourceWrapper in resourceSet.Resources)
            {
                yield return(deserializer.ReadInline(resourceWrapper, elementType, readContext));
            }
        }
Example #11
0
        /// <inheritdoc />
        public override async Task <object> ReadAsync(ODataMessageReader messageReader, Type type, ODataDeserializerContext readContext)
        {
            if (messageReader == null)
            {
                throw Error.ArgumentNull(nameof(messageReader));
            }

            if (readContext == null)
            {
                throw Error.ArgumentNull(nameof(readContext));
            }

            ODataEntityReferenceLink entityReferenceLink = await messageReader.ReadEntityReferenceLinkAsync().ConfigureAwait(false);

            if (entityReferenceLink != null)
            {
                return(ResolveContentId(entityReferenceLink.Url, readContext));
            }

            return(null);
        }
        private static object ConvertEnumValue(ODataEnumValue enumValue, ref IEdmTypeReference propertyType,
                                               IODataDeserializerProvider deserializerProvider, ODataDeserializerContext readContext)
        {
            IEdmEnumTypeReference edmEnumType;

            if (propertyType == null)
            {
                // dynamic enum property
                Contract.Assert(!String.IsNullOrEmpty(enumValue.TypeName),
                                "ODataLib should have verified that dynamic enum value has a type name since we provided metadata.");
                IEdmModel model   = readContext.Model;
                IEdmType  edmType = model.FindType(enumValue.TypeName);
                Contract.Assert(edmType.TypeKind == EdmTypeKind.Enum, "ODataLib should have verified that enum value has a enum resource type.");
                edmEnumType  = new EdmEnumTypeReference(edmType as IEdmEnumType, isNullable: true);
                propertyType = edmEnumType;
            }
            else
            {
                edmEnumType = propertyType.AsEnum();
            }

            ODataEdmTypeDeserializer deserializer = deserializerProvider.GetEdmTypeDeserializer(edmEnumType);

            return(deserializer.ReadInline(enumValue, propertyType, readContext));
        }
        internal static void SetDeclaredProperty(object resource, EdmTypeKind propertyKind, string propertyName,
                                                 object propertyValue, IEdmProperty edmProperty, ODataDeserializerContext readContext)
        {
            if (propertyKind == EdmTypeKind.Collection)
            {
                SetCollectionProperty(resource, edmProperty, propertyValue, propertyName);
            }
            else
            {
                if (!readContext.IsUntyped)
                {
                    if (propertyKind == EdmTypeKind.Primitive)
                    {
                        propertyValue = EdmPrimitiveHelpers.ConvertPrimitiveValue(propertyValue,
                                                                                  GetPropertyType(resource, propertyName));
                    }
                }

                SetProperty(resource, propertyName, propertyValue);
            }
        }
        internal static void ApplyProperty(ODataProperty property, IEdmStructuredTypeReference resourceType, object resource,
                                           IODataDeserializerProvider deserializerProvider, ODataDeserializerContext readContext)
        {
            IEdmProperty edmProperty = resourceType.FindProperty(property.Name);

            bool   isDynamicProperty = false;
            string propertyName      = property.Name;

            if (edmProperty != null)
            {
                propertyName = EdmLibHelpers.GetClrPropertyName(edmProperty, readContext.Model);
            }
            else
            {
                IEdmStructuredType structuredType = resourceType.StructuredDefinition();
                isDynamicProperty = structuredType != null && structuredType.IsOpen;
            }

            if (!isDynamicProperty && edmProperty == null)
            {
                throw new ODataException("Does not support untyped value in non-open type.");
            }

            // dynamic properties have null values
            IEdmTypeReference propertyType = edmProperty != null ? edmProperty.Type : null;

            EdmTypeKind propertyKind;
            object      value = ConvertValue(property.Value, ref propertyType, deserializerProvider, readContext,
                                             out propertyKind);

            if (isDynamicProperty)
            {
                SetDynamicProperty(resource, resourceType, propertyKind, propertyName, value, propertyType,
                                   readContext.Model);
            }
            else
            {
                SetDeclaredProperty(resource, propertyKind, propertyName, value, edmProperty, readContext);
            }
        }
        /// <inheritdoc />
        public sealed override object ReadInline(object item, IEdmTypeReference edmType, ODataDeserializerContext readContext)
        {
            if (item == null)
            {
                return(null);
            }

            ODataProperty property = item as ODataProperty;

            if (property == null)
            {
                throw Error.Argument("item", SRResources.ArgumentMustBeOfType, typeof(ODataProperty).Name);
            }

            return(ReadPrimitive(property, readContext));
        }
        /// <inheritdoc />
        public sealed override object ReadInline(object item, IEdmTypeReference edmType, ODataDeserializerContext readContext)
        {
            if (item == null)
            {
                return(null);
            }

            if (edmType == null)
            {
                throw Error.ArgumentNull("edmType");
            }

            if (!edmType.IsCollection())
            {
                throw new SerializationException(
                          Error.Format(SRResources.TypeCannotBeDeserialized, edmType.ToTraceString(), nameof(ODataInputFormatter)));
            }

            IEdmCollectionTypeReference collectionType = edmType.AsCollection();
            IEdmTypeReference           elementType    = collectionType.ElementType();

            ODataCollectionValue collection = item as ODataCollectionValue;

            if (collection == null)
            {
                throw Error.Argument("item", SRResources.ArgumentMustBeOfType, typeof(ODataCollectionValue).Name);
            }
            // Recursion guard to avoid stack overflows
            RuntimeHelpers.EnsureSufficientExecutionStack();

            IEnumerable result = ReadCollectionValue(collection, elementType, readContext);

            if (result != null)
            {
                if (readContext.IsUntyped && elementType.IsEnum())
                {
                    return(result.ConvertToEdmObject(collectionType));
                }
                else
                {
                    Type        elementClrType = EdmLibHelpers.GetClrType(elementType, readContext.Model);
                    IEnumerable castedResult   = _castMethodInfo.MakeGenericMethod(elementClrType).Invoke(null, new object[] { result }) as IEnumerable;
                    return(castedResult);
                }
            }
            return(null);
        }
        private static object ConvertCollectionValue(ODataCollectionValue collection,
            ref IEdmTypeReference propertyType, ODataDeserializerProvider deserializerProvider,
            ODataDeserializerContext readContext)
        {
            IEdmCollectionTypeReference collectionType;
            if (propertyType == null)
            {
                // dynamic collection property
                Contract.Assert(!String.IsNullOrEmpty(collection.TypeName),
                    "ODataLib should have verified that dynamic collection value has a type name " +
                    "since we provided metadata.");

                string elementTypeName = GetCollectionElementTypeName(collection.TypeName, isNested: false);
                IEdmModel model = readContext.Model;
                IEdmSchemaType elementType = model.FindType(elementTypeName);
                Contract.Assert(elementType != null);
                collectionType =
                    new EdmCollectionTypeReference(
                        new EdmCollectionType(elementType.ToEdmTypeReference(isNullable: false)));
                propertyType = collectionType;
            }
            else
            {
                collectionType = propertyType as IEdmCollectionTypeReference;
                Contract.Assert(collectionType != null, "The type for collection must be a IEdmCollectionType.");
            }

            ODataEdmTypeDeserializer deserializer = deserializerProvider.GetEdmTypeDeserializer(collectionType);
            return deserializer.ReadInline(collection, collectionType, readContext);
        }
Example #18
0
        /// <summary>
        /// Create <see cref="ODataResourceWrapper"/> from a <see cref="ODataEntityReferenceLinkWrapper"/>
        /// </summary>
        /// <param name="edmPropertyType">The Edm property type.</param>
        /// <param name="refLink">The reference link.</param>
        /// <param name="readContext">The reader context.</param>
        /// <returns>The created <see cref="ODataResourceSetWrapper"/>.</returns>
        private static ODataResourceWrapper CreateResourceWrapper(IEdmTypeReference edmPropertyType, ODataEntityReferenceLinkWrapper refLink, ODataDeserializerContext readContext)
        {
            Contract.Assert(edmPropertyType != null);
            Contract.Assert(refLink != null);
            Contract.Assert(readContext != null);

            ODataResource resource = new ODataResource
            {
                TypeName = edmPropertyType.FullName(),
            };

            resource.Properties = CreateKeyProperties(refLink.EntityReferenceLink.Url, readContext) ?? Array.Empty <ODataProperty>();
            ODataResourceWrapper resourceWrapper = new ODataResourceWrapper(resource);

            foreach (var instanceAnnotation in refLink.EntityReferenceLink.InstanceAnnotations)
            {
                resource.InstanceAnnotations.Add(instanceAnnotation);
            }

            return(resourceWrapper);
        }
Example #19
0
 /// <summary>
 /// Reads an <see cref="IODataRequestMessage"/> using messageReader.
 /// </summary>
 /// <param name="messageReader">The messageReader to use.</param>
 /// <param name="type">The type of the object to read into.</param>
 /// <param name="readContext">The read context.</param>
 /// <returns>The deserialized object.</returns>
 public virtual object Read(ODataMessageReader messageReader, Type type, ODataDeserializerContext readContext)
 {
     throw Error.NotSupported(SRResources.DeserializerDoesNotSupportRead, GetType().Name);
 }
        internal static void ApplyProperty(ODataProperty property, IEdmStructuredTypeReference resourceType, object resource,
                                           ODataDeserializerProvider deserializerProvider, ODataDeserializerContext readContext)
        {
            IEdmStructuredType structuredType = resourceType.StructuredDefinition();
            IEdmProperty       edmProperty    = structuredType == null ? null : structuredType.ResolveProperty(property.Name);

            bool   isDynamicProperty = false;
            string propertyName      = property.Name;

            if (edmProperty != null)
            {
                propertyName = readContext.Model.GetClrPropertyName(edmProperty);
            }
            else
            {
                isDynamicProperty = structuredType != null && structuredType.IsOpen;
            }

            if (!isDynamicProperty && edmProperty == null)
            {
                throw new ODataException(
                          Error.Format(SRResources.CannotDeserializeUnknownProperty, property.Name, resourceType.Definition));
            }

            // dynamic properties have null values
            IEdmTypeReference propertyType = edmProperty != null ? edmProperty.Type : null;

            EdmTypeKind propertyKind;
            object      value = ConvertValue(property.Value, ref propertyType, deserializerProvider, readContext,
                                             out propertyKind);

            if (isDynamicProperty)
            {
                SetDynamicProperty(resource, resourceType, propertyKind, propertyName, value, propertyType,
                                   readContext.Model);
            }
            else
            {
                SetDeclaredProperty(resource, propertyKind, propertyName, value, edmProperty, readContext);
            }
        }
Example #21
0
        /// <summary>
        /// Create <see cref="ODataResourceSetWrapper"/> from a set of <see cref="ODataEntityReferenceLinkWrapper"/>
        /// </summary>
        /// <param name="edmPropertyType">The Edm property type.</param>
        /// <param name="refLinks">The reference links.</param>
        /// <param name="readContext">The reader context.</param>
        /// <returns>The created <see cref="ODataResourceSetWrapper"/>.</returns>
        private static ODataResourceSetWrapper CreateResourceSetWrapper(IEdmCollectionTypeReference edmPropertyType,
                                                                        ODataEntityReferenceLinkWrapper[] refLinks, ODataDeserializerContext readContext)
        {
            Contract.Assert(edmPropertyType != null);
            Contract.Assert(refLinks != null);
            Contract.Assert(readContext != null);

            ODataResourceSet resourceSet = new ODataResourceSet
            {
                TypeName = edmPropertyType.FullName(),
            };

            IEdmTypeReference       elementType        = edmPropertyType.ElementType();
            ODataResourceSetWrapper resourceSetWrapper = new ODataResourceSetWrapper(resourceSet);

            foreach (ODataEntityReferenceLinkWrapper refLinkWrapper in refLinks)
            {
                ODataResourceWrapper resourceWrapper = CreateResourceWrapper(elementType, refLinkWrapper, readContext);
                resourceSetWrapper.Resources.Add(resourceWrapper);
            }

            return(resourceSetWrapper);
        }
Example #22
0
        /// <summary>
        /// Deserializes the delete infromation from <paramref name="resourceWrapper"/> into <paramref name="resource"/>.
        /// </summary>
        /// <param name="resource">The object into which the nested properties should be read.</param>
        /// <param name="resourceWrapper">The resource object containing the nested properties.</param>
        /// <param name="readContext">The deserializer context.</param>
        public virtual void ApplyDeletedResource(object resource, ODataResourceWrapper resourceWrapper, ODataDeserializerContext readContext)
        {
            if (resourceWrapper == null)
            {
                throw Error.ArgumentNull(nameof(resourceWrapper));
            }

            if (readContext == null)
            {
                throw Error.ArgumentNull(nameof(readContext));
            }

            if (!resourceWrapper.IsDeletedResource)
            {
                return;
            }

            if (resourceWrapper.Resource is ODataDeletedResource deletedResource)
            {
                if (resource is IDeltaDeletedResource deltaDeletedResource)
                {
                    // typed scenario
                    deltaDeletedResource.Id     = deletedResource.Id;
                    deltaDeletedResource.Reason = deletedResource.Reason;
                }
                else if (resource is IEdmDeltaDeletedResourceObject deletedObject)
                {
                    // non-typed scenario
                    deletedObject.Id     = deletedResource.Id;
                    deletedObject.Reason = deletedResource.Reason ?? DeltaDeletedEntryReason.Deleted;
                }
            }
        }
Example #23
0
        /// <summary>
        /// Update the resource wrapper if it's have the "Id" value.
        /// </summary>
        /// <param name="resourceWrapper">The resource wrapper.</param>
        /// <param name="readContext">The read context.</param>
        /// <returns>The resource wrapper.</returns>
        private ODataResourceWrapper UpdateResourceWrapper(ODataResourceWrapper resourceWrapper, ODataDeserializerContext readContext)
        {
            Contract.Assert(readContext != null);

            if (resourceWrapper == null ||
                resourceWrapper.Resource == null ||
                resourceWrapper.Resource.Id == null)
            {
                return(resourceWrapper);
            }

            IEnumerable <ODataProperty> keys = CreateKeyProperties(resourceWrapper.Resource.Id, readContext);

            if (keys == null)
            {
                return(resourceWrapper);
            }

            if (resourceWrapper.Resource.Properties == null)
            {
                resourceWrapper.Resource.Properties = keys;
            }
            else
            {
                IDictionary <string, ODataProperty> newPropertiesDic = resourceWrapper.Resource.Properties.ToDictionary(p => p.Name, p => p);
                foreach (var key in keys)
                {
                    // Logic: if we have the key property, try to keep the key property and get rid of the key value from ID.
                    // Need to double confirm whether it is the right logic?
                    if (!newPropertiesDic.ContainsKey(key.Name))
                    {
                        newPropertiesDic[key.Name] = key;
                    }
                }

                resourceWrapper.Resource.Properties = newPropertiesDic.Values;
            }

            return(resourceWrapper);
        }
Example #24
0
        /// <summary>
        /// Deserializes the nested property from <paramref name="resourceInfoWrapper"/> into <paramref name="resource"/>.
        /// </summary>
        /// <param name="resource">The object into which the nested property should be read.</param>
        /// <param name="resourceInfoWrapper">The nested resource info.</param>
        /// <param name="structuredType">The type of the resource.</param>
        /// <param name="readContext">The deserializer context.</param>
        public virtual void ApplyNestedProperty(object resource, ODataNestedResourceInfoWrapper resourceInfoWrapper,
                                                IEdmStructuredTypeReference structuredType, ODataDeserializerContext readContext)
        {
            if (resource == null)
            {
                throw Error.ArgumentNull(nameof(resource));
            }

            if (resourceInfoWrapper == null)
            {
                throw Error.ArgumentNull(nameof(resourceInfoWrapper));
            }

            IEdmProperty edmProperty = structuredType.FindProperty(resourceInfoWrapper.NestedResourceInfo.Name);

            if (edmProperty == null)
            {
                if (!structuredType.IsOpen())
                {
                    throw new ODataException(
                              Error.Format(SRResources.NestedPropertyNotfound, resourceInfoWrapper.NestedResourceInfo.Name,
                                           structuredType.FullName()));
                }
            }

            IList <ODataItemWrapper> nestedItems;
            var referenceLinks = resourceInfoWrapper.NestedItems.OfType <ODataEntityReferenceLinkWrapper>().ToArray();

            if (referenceLinks.Length > 0)
            {
                // Be noted:
                // 1) OData v4.0, it's "*****@*****.**", and we get "ODataEntityReferenceLinkWrapper"(s) for that.
                // 2) OData v4.01, it's {"odata.id" ...}, and we get "ODataResource"(s) for that.
                // So, in OData v4, if it's a single, NestedItems contains one ODataEntityReferenceLinkWrapper,
                // if it's a collection, NestedItems contains multiple ODataEntityReferenceLinkWrapper(s)
                // We can use the following codes to adjust the `ODataEntityReferenceLinkWrapper` to `ODataResourceWrapper`.
                // In OData v4.01, we will not be here.
                // Only supports declared property
                Contract.Assert(edmProperty != null);

                nestedItems = new List <ODataItemWrapper>();
                if (edmProperty.Type.IsCollection())
                {
                    IEdmCollectionTypeReference edmCollectionTypeReference = edmProperty.Type.AsCollection();
                    ODataResourceSetWrapper     resourceSetWrapper         = CreateResourceSetWrapper(edmCollectionTypeReference, referenceLinks, readContext);
                    nestedItems.Add(resourceSetWrapper);
                }
                else
                {
                    ODataResourceWrapper resourceWrapper = CreateResourceWrapper(edmProperty.Type, referenceLinks[0], readContext);
                    nestedItems.Add(resourceWrapper);
                }
            }
            else
            {
                nestedItems = resourceInfoWrapper.NestedItems;
            }

            foreach (ODataItemWrapper childItem in nestedItems)
            {
                // it maybe null.
                if (childItem == null)
                {
                    if (edmProperty == null)
                    {
                        // for the dynamic, OData.net has a bug. see https://github.com/OData/odata.net/issues/977
                        ApplyDynamicResourceInNestedProperty(resourceInfoWrapper.NestedResourceInfo.Name, resource,
                                                             structuredType, null, readContext);
                    }
                    else
                    {
                        ApplyResourceInNestedProperty(edmProperty, resource, null, readContext);
                    }
                }

                ODataResourceSetWrapper resourceSetWrapper = childItem as ODataResourceSetWrapper;
                if (resourceSetWrapper != null)
                {
                    if (edmProperty == null)
                    {
                        ApplyDynamicResourceSetInNestedProperty(resourceInfoWrapper.NestedResourceInfo.Name,
                                                                resource, structuredType, resourceSetWrapper, readContext);
                    }
                    else
                    {
                        ApplyResourceSetInNestedProperty(edmProperty, resource, resourceSetWrapper, readContext);
                    }

                    continue;
                }

                if (childItem is ODataDeltaResourceSetWrapper deltaResourceSetWrapper)
                {
                    Contract.Assert(edmProperty != null, "nested delta resource cannot be dynamic property!");
                    ApplyNestedDeltaResourceSet(edmProperty, resource, deltaResourceSetWrapper, readContext);
                    continue;
                }

                // It must be resource by now.
                ODataResourceWrapper resourceWrapper = (ODataResourceWrapper)childItem;
                if (resourceWrapper != null)
                {
                    if (edmProperty == null)
                    {
                        ApplyDynamicResourceInNestedProperty(resourceInfoWrapper.NestedResourceInfo.Name, resource,
                                                             structuredType, resourceWrapper, readContext);
                    }
                    else
                    {
                        ApplyResourceInNestedProperty(edmProperty, resource, resourceWrapper, readContext);
                    }
                }
            }
        }
        /// <summary>
        /// Deserializes the given <paramref name="resourceWrapper"/> under the given <paramref name="readContext"/>.
        /// </summary>
        /// <param name="resourceWrapper">The OData resource to deserialize.</param>
        /// <param name="structuredType">The type of the resource to deserialize.</param>
        /// <param name="readContext">The deserializer context.</param>
        /// <returns>The deserialized resource.</returns>
        public virtual object ReadResource(ODataResourceWrapper resourceWrapper, IEdmStructuredTypeReference structuredType,
                                           ODataDeserializerContext readContext)
        {
            if (resourceWrapper == null)
            {
                throw new ArgumentNullException(nameof(resourceWrapper));
            }

            if (readContext == null)
            {
                throw new ArgumentNullException(nameof(readContext));
            }

            if (!String.IsNullOrEmpty(resourceWrapper.Resource.TypeName) && structuredType.FullName() != resourceWrapper.Resource.TypeName)
            {
                // received a derived type in a base type deserializer. delegate it to the appropriate derived type deserializer.
                IEdmModel model = readContext.Model;

                if (model == null)
                {
                    throw Error.Argument("readContext", SRResources.ModelMissingFromReadContext);
                }

                IEdmStructuredType actualType = model.FindType(resourceWrapper.Resource.TypeName) as IEdmStructuredType;
                if (actualType == null)
                {
                    throw new ODataException(Error.Format(SRResources.ResourceTypeNotInModel, resourceWrapper.Resource.TypeName));
                }

                if (actualType.IsAbstract)
                {
                    string message = Error.Format(SRResources.CannotInstantiateAbstractResourceType, resourceWrapper.Resource.TypeName);
                    throw new ODataException(message);
                }

                IEdmTypeReference actualStructuredType;
                IEdmEntityType    actualEntityType = actualType as IEdmEntityType;
                if (actualEntityType != null)
                {
                    actualStructuredType = new EdmEntityTypeReference(actualEntityType, isNullable: false);
                }
                else
                {
                    actualStructuredType = new EdmComplexTypeReference(actualType as IEdmComplexType, isNullable: false);
                }

                ODataEdmTypeDeserializer deserializer = DeserializerProvider.GetEdmTypeDeserializer(actualStructuredType);
                if (deserializer == null)
                {
                    throw new SerializationException(
                              Error.Format(SRResources.TypeCannotBeDeserialized, actualEntityType.FullName()));
                }

                object resource = deserializer.ReadInline(resourceWrapper, actualStructuredType, readContext);

                EdmStructuredObject structuredObject = resource as EdmStructuredObject;
                if (structuredObject != null)
                {
                    structuredObject.ExpectedEdmType = structuredType.StructuredDefinition();
                }

                return(resource);
            }
            else
            {
                object resource = CreateResourceInstance(structuredType, readContext);
                ApplyResourceProperties(resource, resourceWrapper, structuredType, readContext);
                return(resource);
            }
        }
Example #26
0
        /// <summary>
        /// Deserializes the given <paramref name="structuralProperty"/> into <paramref name="resource"/>.
        /// </summary>
        /// <param name="resource">The object into which the structural property should be read.</param>
        /// <param name="structuralProperty">The structural property.</param>
        /// <param name="structuredType">The type of the resource.</param>
        /// <param name="readContext">The deserializer context.</param>
        public virtual void ApplyStructuralProperty(object resource, ODataProperty structuralProperty,
                                                    IEdmStructuredTypeReference structuredType, ODataDeserializerContext readContext)
        {
            if (resource == null)
            {
                throw new ArgumentNullException(nameof(resource));
            }

            if (structuralProperty == null)
            {
                throw new ArgumentNullException(nameof(structuralProperty));
            }

            if (structuredType == null)
            {
                throw new ArgumentNullException(nameof(structuredType));
            }

            if (readContext == null)
            {
                throw new ArgumentNullException(nameof(readContext));
            }

            DeserializationHelpers.ApplyProperty(structuralProperty, structuredType, resource, DeserializerProvider, readContext);
        }
        /// <summary>
        /// Deserializes the nested properties from <paramref name="resourceWrapper"/> into <paramref name="resource"/>.
        /// </summary>
        /// <param name="resource">The object into which the nested properties should be read.</param>
        /// <param name="resourceWrapper">The resource object containing the nested properties.</param>
        /// <param name="structuredType">The type of the resource.</param>
        /// <param name="readContext">The deserializer context.</param>
        public virtual void ApplyNestedProperties(object resource, ODataResourceWrapper resourceWrapper,
                                                  IEdmStructuredTypeReference structuredType, ODataDeserializerContext readContext)
        {
            if (resourceWrapper == null)
            {
                throw new ArgumentNullException(nameof(resourceWrapper));
            }

            foreach (ODataNestedResourceInfoWrapper nestedResourceInfo in resourceWrapper.NestedResourceInfos)
            {
                ApplyNestedProperty(resource, nestedResourceInfo, structuredType, readContext);
            }
        }
Example #28
0
 private void ApplyResourceProperties(object resource, ODataResourceWrapper resourceWrapper,
                                      IEdmStructuredTypeReference structuredType, ODataDeserializerContext readContext)
 {
     ApplyStructuralProperties(resource, resourceWrapper, structuredType, readContext);
     ApplyNestedProperties(resource, resourceWrapper, structuredType, readContext);
 }
        /// <inheritdoc />
        public override async Task <object> ReadAsync(ODataMessageReader messageReader, Type type, ODataDeserializerContext readContext)
        {
            if (messageReader == null)
            {
                throw new ArgumentNullException(nameof(messageReader));
            }

            if (readContext == null)
            {
                throw new ArgumentNullException(nameof(readContext));
            }

            IEdmTypeReference edmType = readContext.GetEdmType(type);

            Contract.Assert(edmType != null);

            if (!edmType.IsStructured())
            {
                throw Error.Argument("type", SRResources.ArgumentMustBeOfType, "Structured");
            }

            IEdmStructuredTypeReference structuredType = edmType.AsStructured();

            IEdmNavigationSource navigationSource = null;

            if (structuredType.IsEntity())
            {
                if (readContext.Path == null)
                {
                    throw Error.Argument("readContext", SRResources.ODataPathMissing);
                }

                navigationSource = readContext.Path.GetNavigationSource();
                if (navigationSource == null)
                {
                    throw new SerializationException(SRResources.NavigationSourceMissingDuringDeserialization);
                }
            }

            ODataReader odataReader = await messageReader
                                      .CreateODataResourceReaderAsync(navigationSource, structuredType.StructuredDefinition()).ConfigureAwait(false);

            ODataResourceWrapper topLevelResource = await odataReader.ReadResourceOrResourceSetAsync().ConfigureAwait(false)
                                                    as ODataResourceWrapper;

            Contract.Assert(topLevelResource != null);

            return(ReadInline(topLevelResource, structuredType, readContext));
        }
Example #30
0
        private void ApplyResourceInNestedProperty(IEdmProperty nestedProperty, object resource,
                                                   ODataResourceWrapper resourceWrapper, ODataDeserializerContext readContext)
        {
            Contract.Assert(nestedProperty != null);
            Contract.Assert(resource != null);
            Contract.Assert(readContext != null);

            object value = ReadNestedResourceInline(resourceWrapper, nestedProperty.Type, readContext);

            // First resolve Data member alias or annotation, then set the regular
            // or delta resource accordingly.
            string propertyName = readContext.Model.GetClrPropertyName(nestedProperty);

            DeserializationHelpers.SetProperty(resource, propertyName, value);
        }
 /// <summary>
 /// Deserializes the item into a new object of type corresponding to <paramref name="edmType"/>.
 /// </summary>
 /// <param name="item">The item to deserialize.</param>
 /// <param name="edmType">The EDM type of the object to read into.</param>
 /// <param name="readContext">The <see cref="ODataDeserializerContext"/>.</param>
 /// <returns>The deserialized object.</returns>
 public virtual object ReadInline(object item, IEdmTypeReference edmType, ODataDeserializerContext readContext)
 {
     throw Error.NotSupported(SRResources.DoesNotSupportReadInLine, GetType().Name);
 }
Example #32
0
        private void ApplyDynamicResourceInNestedProperty(string propertyName, object resource, IEdmStructuredTypeReference resourceStructuredType,
                                                          ODataResourceWrapper resourceWrapper, ODataDeserializerContext readContext)
        {
            Contract.Assert(resource != null);
            Contract.Assert(readContext != null);

            object value = null;

            if (resourceWrapper != null)
            {
                IEdmSchemaType    elementType      = readContext.Model.FindDeclaredType(resourceWrapper.Resource.TypeName);
                IEdmTypeReference edmTypeReference = elementType.ToEdmTypeReference(true);

                value = ReadNestedResourceInline(resourceWrapper, edmTypeReference, readContext);
            }

            DeserializationHelpers.SetDynamicProperty(resource, propertyName, value,
                                                      resourceStructuredType.StructuredDefinition(), readContext.Model);
        }
        internal static void SetDynamicProperty(object resource, string propertyName, object value,
            IEdmStructuredType structuredType, ODataDeserializerContext readContext)
        {
            IDelta delta = resource as IDelta;
            if (delta != null)
            {
                delta.TrySetPropertyValue(propertyName, value);
            }
            else
            {
                PropertyInfo propertyInfo = EdmLibHelpers.GetDynamicPropertyDictionary(structuredType,
                    readContext.Model);
                if (propertyInfo == null)
                {
                    return;
                }

                IDictionary<string, object> dynamicPropertyDictionary;
                object dynamicDictionaryObject = propertyInfo.GetValue(resource);
                if (dynamicDictionaryObject == null)
                {
                    if (!propertyInfo.CanWrite)
                    {
                        throw Error.InvalidOperation(SRResources.CannotSetDynamicPropertyDictionary, propertyName,
                            resource.GetType().FullName);
                    }

                    dynamicPropertyDictionary = new Dictionary<string, object>();
                    propertyInfo.SetValue(resource, dynamicPropertyDictionary);
                }
                else
                {
                    dynamicPropertyDictionary = (IDictionary<string, object>)dynamicDictionaryObject;
                }

                if (dynamicPropertyDictionary.ContainsKey(propertyName))
                {
                    throw Error.InvalidOperation(SRResources.DuplicateDynamicPropertyNameFound,
                        propertyName, structuredType.FullTypeName());
                }

                dynamicPropertyDictionary.Add(propertyName, value);
            }
        }
Example #34
0
        private object ReadNestedResourceInline(ODataResourceWrapper resourceWrapper, IEdmTypeReference edmType, ODataDeserializerContext readContext)
        {
            Contract.Assert(edmType != null);
            Contract.Assert(readContext != null);

            if (resourceWrapper == null)
            {
                return(null);
            }

            ODataEdmTypeDeserializer deserializer = DeserializerProvider.GetEdmTypeDeserializer(edmType);

            if (deserializer == null)
            {
                throw new SerializationException(Error.Format(SRResources.TypeCannotBeDeserialized, edmType.FullName()));
            }

            IEdmStructuredTypeReference structuredType = edmType.AsStructured();

            var nestedReadContext = new ODataDeserializerContext
            {
                Path     = readContext.Path,
                Model    = readContext.Model,
                Request  = readContext.Request,
                TimeZone = readContext.TimeZone
            };

            Type clrType;

            if (readContext.IsNoClrType)
            {
                clrType = structuredType.IsEntity()
                    ? typeof(EdmEntityObject)
                    : typeof(EdmComplexObject);
            }
            else
            {
                clrType = readContext.Model.GetClrType(structuredType);

                if (clrType == null)
                {
                    throw new ODataException(
                              Error.Format(SRResources.MappingDoesNotContainResourceType, structuredType.FullName()));
                }
            }

            nestedReadContext.ResourceType = readContext.IsDeltaOfT
                ? typeof(Delta <>).MakeGenericType(clrType)
                : clrType;
            return(deserializer.ReadInline(resourceWrapper, edmType, nestedReadContext));
        }
        internal static object ConvertValue(object oDataValue, ref IEdmTypeReference propertyType, ODataDeserializerProvider deserializerProvider,
            ODataDeserializerContext readContext, out EdmTypeKind typeKind)
        {
            if (oDataValue == null)
            {
                typeKind = EdmTypeKind.None;
                return null;
            }

            ODataComplexValue complexValue = oDataValue as ODataComplexValue;
            if (complexValue != null)
            {
                typeKind = EdmTypeKind.Complex;
                return ConvertComplexValue(complexValue, ref propertyType, deserializerProvider, readContext);
            }

            ODataEnumValue enumValue = oDataValue as ODataEnumValue;
            if (enumValue != null)
            {
                typeKind = EdmTypeKind.Enum;
                return ConvertEnumValue(enumValue, ref propertyType, deserializerProvider, readContext);
            }

            ODataCollectionValue collection = oDataValue as ODataCollectionValue;
            if (collection != null)
            {
                typeKind = EdmTypeKind.Collection;
                return ConvertCollectionValue(collection, ref propertyType, deserializerProvider, readContext);
            }
            
            typeKind = EdmTypeKind.Primitive;
            return oDataValue;
        }
Example #36
0
        private void ApplyResourceSetInNestedProperty(IEdmProperty nestedProperty, object resource,
                                                      ODataResourceSetWrapper resourceSetWrapper, ODataDeserializerContext readContext)
        {
            Contract.Assert(nestedProperty != null);
            Contract.Assert(resource != null);
            Contract.Assert(readContext != null);

            object value = ReadNestedResourceSetInline(resourceSetWrapper, nestedProperty.Type, readContext);

            string propertyName = readContext.Model.GetClrPropertyName(nestedProperty);

            DeserializationHelpers.SetCollectionProperty(resource, nestedProperty, value, propertyName);
        }
        private static object ConvertEnumValue(ODataEnumValue enumValue, ref IEdmTypeReference propertyType,
            ODataDeserializerProvider deserializerProvider, ODataDeserializerContext readContext)
        {
            IEdmEnumTypeReference edmEnumType;
            if (propertyType == null)
            {
                // dynamic enum property
                Contract.Assert(!String.IsNullOrEmpty(enumValue.TypeName),
                    "ODataLib should have verified that dynamic enum value has a type name since we provided metadata.");
                IEdmModel model = readContext.Model;
                IEdmType edmType = model.FindType(enumValue.TypeName);
                Contract.Assert(edmType.TypeKind == EdmTypeKind.Enum, "ODataLib should have verified that enum value has a enum resource type.");
                edmEnumType = new EdmEnumTypeReference(edmType as IEdmEnumType, isNullable: true);
                propertyType = edmEnumType;
            }
            else
            {
                edmEnumType = propertyType.AsEnum();
            }

            ODataEdmTypeDeserializer deserializer = deserializerProvider.GetEdmTypeDeserializer(edmEnumType);
            return deserializer.ReadInline(enumValue, propertyType, readContext);
        }
Example #38
0
        private void ApplyDynamicResourceSetInNestedProperty(string propertyName, object resource, IEdmStructuredTypeReference structuredType,
                                                             ODataResourceSetWrapper resourceSetWrapper, ODataDeserializerContext readContext)
        {
            Contract.Assert(resource != null);
            Contract.Assert(readContext != null);

            if (string.IsNullOrEmpty(resourceSetWrapper.ResourceSet.TypeName))
            {
                string message = Error.Format(SRResources.DynamicResourceSetTypeNameIsRequired, propertyName);
                throw new ODataException(message);
            }

            string elementTypeName =
                DeserializationHelpers.GetCollectionElementTypeName(resourceSetWrapper.ResourceSet.TypeName,
                                                                    isNested: false);
            IEdmSchemaType elementType = readContext.Model.FindDeclaredType(elementTypeName);

            IEdmTypeReference          edmTypeReference = elementType.ToEdmTypeReference(true);
            EdmCollectionTypeReference collectionType   = new EdmCollectionTypeReference(new EdmCollectionType(edmTypeReference));

            ODataEdmTypeDeserializer deserializer = DeserializerProvider.GetEdmTypeDeserializer(collectionType);

            if (deserializer == null)
            {
                throw new SerializationException(Error.Format(SRResources.TypeCannotBeDeserialized, collectionType.FullName()));
            }

            IEnumerable value  = ReadNestedResourceSetInline(resourceSetWrapper, collectionType, readContext) as IEnumerable;
            object      result = value;

            if (value != null)
            {
                if (readContext.IsNoClrType)
                {
                    result = value.ConvertToEdmObject(collectionType);
                }
            }

            DeserializationHelpers.SetDynamicProperty(resource, structuredType, EdmTypeKind.Collection, propertyName,
                                                      result, collectionType, readContext.Model);
        }
Example #39
0
        private void ApplyNestedDeltaResourceSet(IEdmProperty nestedProperty, object resource,
                                                 ODataDeltaResourceSetWrapper deltaResourceSetWrapper, ODataDeserializerContext readContext)
        {
            Contract.Assert(nestedProperty != null);
            Contract.Assert(resource != null);
            Contract.Assert(readContext != null);

            IEdmTypeReference        edmType      = nestedProperty.Type;
            ODataEdmTypeDeserializer deserializer = DeserializerProvider.GetEdmTypeDeserializer(edmType, true);

            if (deserializer == null)
            {
                throw new SerializationException(Error.Format(SRResources.TypeCannotBeDeserialized, edmType.FullName()));
            }

            IEdmStructuredTypeReference structuredType    = edmType.AsCollection().ElementType().AsStructured();
            ODataDeserializerContext    nestedReadContext = readContext.CloneWithoutType();

            if (readContext.IsNoClrType)
            {
                nestedReadContext.ResourceType = typeof(EdmChangedObjectCollection);
            }
            else
            {
                Type clrType = readContext.Model.GetClrType(structuredType);

                if (clrType == null)
                {
                    throw new ODataException(
                              Error.Format(SRResources.MappingDoesNotContainResourceType, structuredType.FullName()));
                }

                nestedReadContext.ResourceType = typeof(DeltaSet <>).MakeGenericType(clrType);
            }

            object value = deserializer.ReadInline(deltaResourceSetWrapper, edmType, nestedReadContext);

            string propertyName = readContext.Model.GetClrPropertyName(nestedProperty);

            DeserializationHelpers.SetCollectionProperty(resource, nestedProperty, value, propertyName);
        }
        /// <inheritdoc />
        public override async Task <object> ReadAsync(ODataMessageReader messageReader, Type type, ODataDeserializerContext readContext)
        {
            if (messageReader == null)
            {
                throw Error.ArgumentNull("messageReader");
            }

            if (readContext == null)
            {
                throw new ArgumentNullException(nameof(readContext));
            }

            IEdmTypeReference edmType = readContext.GetEdmType(type);

            Contract.Assert(edmType != null);

            if (!edmType.IsCollection())
            {
                throw Error.Argument("type", SRResources.ArgumentMustBeOfType, EdmTypeKind.Collection);
            }

            IEdmCollectionTypeReference collectionType = edmType.AsCollection();
            IEdmTypeReference           elementType    = collectionType.ElementType();
            ODataCollectionReader       reader         = await messageReader.CreateODataCollectionReaderAsync(elementType).ConfigureAwait(false);

            return(ReadInline(await ReadCollectionAsync(reader).ConfigureAwait(false), edmType, readContext));
        }