Example #1
0
        public async Task ReadDeletedLinkInDeltaResourceSetWorksAsExpected2()
        {
            // Arrange
            string payload = "{\"@context\":\"http://example.com/$metadata#Customers/$delta\"," +
                             "\"value\":[" +
                             "{" +
                             "\"@removed\":{\"reason\":\"changed\"}," +
                             "\"CustomerID\":1," +
                             "\"Order@delta\":{" +
                             "\"@context\":\"#Orders/$deletedEntity\"," +
                             "\"@removed\":{\"reason\":\"deleted\"}," +
                             "\"OrderId\":10" +
                             "}" +
                             "}" +
                             "]" +
                             "}";

            IEdmEntitySet customers = Model.EntityContainer.FindEntitySet("Customers");

            Assert.NotNull(customers); // Guard

            // Act
            Func <ODataMessageReader, Task <ODataReader> > func = mr => mr.CreateODataDeltaResourceSetReaderAsync(customers, customers.EntityType());
            ODataItemWrapper item = await ReadPayloadAsync(payload, Model, func, ODataVersion.V401);

            // Assert
            Assert.NotNull(item);

            // --- DeltaResourceSet
            //      |--- DeleteResource (Changed)
            //         |--- NestedResourceInfo
            //            |--- DeleteResource (Deleted)
            ODataDeltaResourceSetWrapper deltaResourceSet       = Assert.IsType <ODataDeltaResourceSetWrapper>(item);
            ODataItemWrapper             deltaItem              = Assert.Single(deltaResourceSet.DeltaItems);
            ODataResourceWrapper         deletedResourceWrapper = Assert.IsType <ODataResourceWrapper>(deltaItem);
            ODataDeletedResource         deletedResource        = Assert.IsType <ODataDeletedResource>(deletedResourceWrapper.Resource);

            Assert.Equal(DeltaDeletedEntryReason.Changed, deletedResource.Reason);

            ODataNestedResourceInfoWrapper nestedResourceInfo = Assert.Single(deletedResourceWrapper.NestedResourceInfos);

            Assert.Equal("Order", nestedResourceInfo.NestedResourceInfo.Name);
            Assert.False(nestedResourceInfo.NestedResourceInfo.IsCollection);

            ODataItemWrapper     nestedItem    = Assert.Single(nestedResourceInfo.NestedItems);
            ODataResourceWrapper orderResource = Assert.IsType <ODataResourceWrapper>(nestedItem);

            Assert.True(orderResource.IsDeletedResource);
            ODataDeletedResource innerDeletedResource = Assert.IsType <ODataDeletedResource>(orderResource.Resource);

            Assert.Equal(DeltaDeletedEntryReason.Deleted, innerDeletedResource.Reason);

            ODataProperty property = Assert.Single(innerDeletedResource.Properties);

            Assert.Equal("OrderId", property.Name);
            Assert.Equal(10, property.Value);
        }
Example #2
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);
        }
Example #3
0
        public void ReadDeltaResourceSet_Calls_ReadInlineForEachDeltaItem()
        {
            // Arrange
            IEdmModel      model    = GetEdmModel();
            IEdmEntityType customer = model.SchemaElements.OfType <IEdmEntityType>().First(c => c.Name == "Customer");
            IEdmStructuredTypeReference elementType = new EdmEntityTypeReference(customer, true);

            Mock <IODataDeserializerProvider> deserializerProvider = new Mock <IODataDeserializerProvider>();
            Mock <ODataEdmTypeDeserializer>   resourceDeserializer = new Mock <ODataEdmTypeDeserializer>(ODataPayloadKind.Resource);

            ODataDeltaResourceSetDeserializer deserializer = new ODataDeltaResourceSetDeserializer(deserializerProvider.Object);

            ODataDeltaResourceSetWrapper deltaResourceSetWrapper = new ODataDeltaResourceSetWrapper(new ODataDeltaResourceSet());

            Uri source = new Uri("Customers(8)", UriKind.RelativeOrAbsolute);
            Uri target = new Uri("Orders(10645)", UriKind.RelativeOrAbsolute);

            deltaResourceSetWrapper.DeltaItems.Add(new ODataResourceWrapper(new ODataResource {
                Id = new Uri("http://a1/")
            }));
            deltaResourceSetWrapper.DeltaItems.Add(new ODataResourceWrapper(new ODataDeletedResource {
                Id = new Uri("http://a2/")
            }));
            ODataDeserializerContext readContext = new ODataDeserializerContext()
            {
                Model        = model,
                ResourceType = typeof(DeltaSet <>)
            };

            deserializerProvider.Setup(p => p.GetEdmTypeDeserializer(elementType, false)).Returns(resourceDeserializer.Object);
            resourceDeserializer.Setup(d => d.ReadInline(deltaResourceSetWrapper.DeltaItems[0], elementType, It.IsAny <ODataDeserializerContext>())).Returns("entry1").Verifiable();
            resourceDeserializer.Setup(d => d.ReadInline(deltaResourceSetWrapper.DeltaItems[1], elementType, It.IsAny <ODataDeserializerContext>())).Returns("entry2").Verifiable();

            // Act
            var result = deserializer.ReadDeltaResourceSet(deltaResourceSetWrapper, elementType, readContext);

            // Assert
            Assert.Equal(new[] { "entry1", "entry2" }, result.OfType <String>());
            resourceDeserializer.Verify();
        }
Example #4
0
        public void ReadInline_Calls_ReadDeltaResourceSet()
        {
            // Arrange
            EdmEntityType               entityType     = new EdmEntityType("NS", "Customer");
            IEdmEntityTypeReference     entityTypeRef  = new EdmEntityTypeReference(entityType, false);
            IEdmCollectionTypeReference collectionType = new EdmCollectionTypeReference(new EdmCollectionType(entityTypeRef));

            Mock <IODataDeserializerProvider>        deserializerProvider = new Mock <IODataDeserializerProvider>();
            Mock <ODataDeltaResourceSetDeserializer> deserializer         = new Mock <ODataDeltaResourceSetDeserializer>(deserializerProvider.Object);

            ODataDeltaResourceSetWrapper wrapper     = new ODataDeltaResourceSetWrapper(new ODataDeltaResourceSet());
            ODataDeserializerContext     readContext = new ODataDeserializerContext();

            deserializer.CallBase = true;
            deserializer.Setup(d => d.ReadDeltaResourceSet(wrapper, It.IsAny <IEdmStructuredTypeReference>(), readContext)).Returns((IEnumerable)null).Verifiable();

            // Act
            var result = deserializer.Object.ReadInline(wrapper, collectionType, readContext);

            // Assert
            deserializer.Verify();
            Assert.Null(result);
        }
        /// <summary>
        /// Deserializes the given <paramref name="deltaResourceSet"/> under the given <paramref name="readContext"/>.
        /// </summary>
        /// <param name="deltaResourceSet">The delta resource set to deserialize.</param>
        /// <param name="elementType">The element type.</param>
        /// <param name="readContext">The deserializer context.</param>
        /// <returns>The deserialized resource set object.</returns>
        public virtual IEnumerable ReadDeltaResourceSet(ODataDeltaResourceSetWrapper deltaResourceSet, IEdmStructuredTypeReference elementType, ODataDeserializerContext readContext)
        {
            if (deltaResourceSet == null)
            {
                throw Error.ArgumentNull(nameof(deltaResourceSet));
            }

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

            // Delta Items
            foreach (ODataItemWrapper itemWrapper in deltaResourceSet.DeltaItems)
            {
                // Deleted Link
                ODataDeltaDeletedLinkWrapper deletedLinkWrapper = itemWrapper as ODataDeltaDeletedLinkWrapper;
                if (deletedLinkWrapper != null)
                {
                    yield return(ReadDeltaDeletedLink(deletedLinkWrapper, elementType, readContext));
                }

                // Added Link
                ODataDeltaLinkWrapper deltaLinkWrapper = itemWrapper as ODataDeltaLinkWrapper;
                if (deltaLinkWrapper != null)
                {
                    yield return(ReadDeltaLink(deltaLinkWrapper, elementType, readContext));
                }

                // Added resource, updated resource and deleted resource
                ODataResourceWrapper resourceWrapper = itemWrapper as ODataResourceWrapper;
                if (resourceWrapper != null)
                {
                    yield return(ReadDeltaResource(resourceWrapper, elementType, readContext));
                }
            }
        }
Example #6
0
        /// <inheritdoc />
        public sealed override object ReadInline(object item, IEdmTypeReference edmType, ODataDeserializerContext readContext)
        {
            if (item == null)
            {
                return(null);
            }

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

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

            if (!edmType.IsCollection() || !edmType.AsCollection().ElementType().IsStructured())
            {
                throw Error.Argument(nameof(edmType), SRResources.TypeMustBeResourceSet, edmType.ToTraceString());
            }

            ODataDeltaResourceSetWrapper resourceSet = item as ODataDeltaResourceSetWrapper;

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

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

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

            IEnumerable result = ReadDeltaResourceSet(resourceSet, readContext);

            if (result != null && elementType.IsComplex())
            {
                if (readContext.IsNoClrType)
                {
                    EdmComplexObjectCollection complexCollection = new EdmComplexObjectCollection(edmType.AsCollection());
                    foreach (EdmComplexObject complexObject in result)
                    {
                        complexCollection.Add(complexObject);
                    }
                    return(complexCollection);
                }
                else
                {
                    Type        elementClrType = readContext.Model.GetClrType(elementType);
                    IEnumerable castedResult   =
                        CastMethodInfo.MakeGenericMethod(elementClrType).Invoke(null, new object[] { result }) as
                        IEnumerable;
                    return(castedResult);
                }
            }
            else
            {
                return(result);
            }
        }
Example #7
0
        /// <summary>
        /// Deserializes the given <paramref name="deltaResourceSet"/> under the given <paramref name="readContext"/>.
        /// </summary>
        /// <param name="deltaResourceSet">The delta resource set to deserialize.</param>
        /// <param name="readContext">The deserializer context.</param>
        /// <returns>The deserialized resource set object.</returns>
        public virtual IEnumerable ReadDeltaResourceSet(ODataDeltaResourceSetWrapper deltaResourceSet, ODataDeserializerContext readContext)
        {
            if (deltaResourceSet == null)
            {
                throw Error.ArgumentNull(nameof(deltaResourceSet));
            }

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

            // resource
            foreach (ODataResourceBaseWrapper resourceBaseWrapper in deltaResourceSet.ResourceBases)
            {
                ODataResourceWrapper        resourceWrapper        = resourceBaseWrapper as ODataResourceWrapper;
                ODataDeletedResourceWrapper deletedResourceWrapper = resourceBaseWrapper as ODataDeletedResourceWrapper;
                if (resourceWrapper != null)
                {
                    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));
                    }

                    IEdmTypeReference        edmTypeReference = actualType.ToEdmTypeReference(true);
                    ODataEdmTypeDeserializer deserializer     = DeserializerProvider.GetEdmTypeDeserializer(edmTypeReference);
                    if (deserializer == null)
                    {
                        throw new SerializationException(
                                  Error.Format(SRResources.TypeCannotBeDeserialized, edmTypeReference.FullName()));
                    }

                    // TODO: normal resource
                    yield return(deserializer.ReadInline(resourceWrapper, edmTypeReference, readContext));
                }
                else
                {
                    // TODO: deleted resource
                }
            }

            // Delta links
            foreach (ODataDeltaLinkBaseWrapper deltaLinkBaseWrapper in deltaResourceSet.DeltaLinks)
            {
                ODataDeltaDeletedLinkWrapper deletedLinkWrapper = deltaLinkBaseWrapper as ODataDeltaDeletedLinkWrapper;
                if (deletedLinkWrapper != null)
                {
                    yield return(ReadDeltaDeletedLink(deletedLinkWrapper, readContext));
                }
                else
                {
                    yield return(ReadDeltaLink((ODataDeltaLinkWrapper)deltaLinkBaseWrapper, readContext));
                }
            }
        }
        /// <inheritdoc />
        public sealed override object ReadInline(object item, IEdmTypeReference edmType, ODataDeserializerContext readContext)
        {
            if (item == null)
            {
                return(null);
            }

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

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

            if (!edmType.IsCollection() || !edmType.AsCollection().ElementType().IsStructured())
            {
                throw Error.Argument(nameof(edmType), SRResources.TypeMustBeResourceSet, edmType.ToTraceString());
            }

            ODataDeltaResourceSetWrapper resourceSet = item as ODataDeltaResourceSetWrapper;

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

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

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

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

            if (result != null)
            {
                if (readContext.IsNoClrType)
                {
                    EdmChangedObjectCollection changedObjCollection = new EdmChangedObjectCollection(elementType.Definition as IEdmEntityType);
                    foreach (IEdmChangedObject changedObject in result)
                    {
                        changedObjCollection.Add(changedObject);
                    }

                    return(changedObjCollection);
                }
                else
                {
                    Type elementClrType     = readContext.Model.GetClrType(elementType);
                    Type changedObjCollType = typeof(DeltaSet <>).MakeGenericType(elementClrType);

                    IDeltaSet deltaSet = Activator.CreateInstance(changedObjCollType) as IDeltaSet;
                    foreach (var delta in result)
                    {
                        IDeltaSetItem deltaItem = delta as IDeltaSetItem;
                        if (deltaItem != null)
                        {
                            deltaSet.Add(deltaItem);
                        }
                    }

                    return(deltaSet);
                }
            }
            else
            {
                return(result);
            }
        }
        public async Task ReadDeletedLinkInDeltaResourceSetWorksAsExpected()
        {
            // Arrange
            string payload = "{" +
                             "\"@odata.context\":\"http://localhost/$metadata#Customers/$delta\"," +
                             "\"@odata.count\":5," +
                             "\"value\":[" +
                             "{" +
                             "\"@odata.id\":\"Customers(42)\"," +
                             "\"Name\":\"Sammy\"" +
                             "}," +
                             "{" +
                             "\"@odata.context\":\"http://localhost/$metadata#Customers/$deletedLink\"," +
                             "\"source\":\"Customers(39)\"," +
                             "\"relationship\":\"Orders\"," +
                             "\"target\":\"Orders(10643)\"" +
                             "}," +
                             "{" +
                             "\"@odata.context\":\"http://localhost/$metadata#Customers/$link\"," +
                             "\"source\":\"Customers(32)\"," +
                             "\"relationship\":\"Orders\"," +
                             "\"target\":\"Orders(10645)\"" +
                             "}," +
                             "{" +
                             "\"@odata.context\":\"http://localhost/$metadata#Orders/$entity\"," +
                             "\"@odata.id\":\"Orders(10643)\"," +
                             "\"Price\": 82" +
                             "}," +
                             "{" +
                             "\"@odata.context\":\"http://localhost/$metadata#Customers/$deletedEntity\"," +
                             "\"id\":\"Customers(21)\"," +
                             "\"reason\":\"deleted\"" +
                             "}" +
                             "]," +
                             "\"@odata.deltaLink\":\"Customers?$expand=Orders&$deltatoken=8015\"" +
                             "}";

            IEdmEntitySet customers = Model.EntityContainer.FindEntitySet("Customers");

            Assert.NotNull(customers); // Guard

            // Act
            Func <ODataMessageReader, Task <ODataReader> > func = mr => mr.CreateODataDeltaResourceSetReaderAsync(customers, customers.EntityType());
            ODataItemWrapper item = await ReadPayloadAsync(payload, Model, func);

            // Assert
            Assert.NotNull(item);

            // --- DeltaResourceSet
            //      |--- Resource (1)
            //      |--- Resource (2)
            //      |--- DeletedResource (1)
            //      |
            //      |--- DeltaDeletedLink
            //      |--- DeltaLink
            ODataDeltaResourceSetWrapper deltaResourceSet = Assert.IsType <ODataDeltaResourceSetWrapper>(item);

            // Resources
            Assert.Equal(3, deltaResourceSet.ResourceBases.Count);
            Assert.Collection(deltaResourceSet.ResourceBases,
                              e =>
            {
                ODataResourceWrapper resource1 = Assert.IsType <ODataResourceWrapper>(e);
                Assert.Equal("Customers(42)", resource1.Resource.Id.OriginalString);
                Assert.Equal("Sammy", resource1.Resource.Properties.First(p => p.Name == "Name").Value);
            },
                              e =>
            {
                ODataResourceWrapper resource2 = Assert.IsType <ODataResourceWrapper>(e);
                Assert.Equal("Orders(10643)", resource2.Resource.Id.OriginalString);
                Assert.Equal(82, resource2.Resource.Properties.First(p => p.Name == "Price").Value);
            },
                              e =>
            {
                ODataDeletedResourceWrapper deletedResource = Assert.IsType <ODataDeletedResourceWrapper>(e);
                Assert.Equal("Customers(21)", deletedResource.DeletedResource.Id.OriginalString);
                Assert.Equal(DeltaDeletedEntryReason.Deleted, deletedResource.DeletedResource.Reason);
            });

            // DeltaLinks
            Assert.Equal(2, deltaResourceSet.DeltaLinks.Count);
            Assert.Collection(deltaResourceSet.DeltaLinks,
                              e =>
            {
                ODataDeltaDeletedLinkWrapper deletedLinkWrapper = Assert.IsType <ODataDeltaDeletedLinkWrapper>(e);
                Assert.Equal("Customers(39)", deletedLinkWrapper.DeltaDeletedLink.Source.OriginalString);
                Assert.Equal("Orders(10643)", deletedLinkWrapper.DeltaDeletedLink.Target.OriginalString);
                Assert.Equal("Orders", deletedLinkWrapper.DeltaDeletedLink.Relationship);
            },
                              e =>
            {
                ODataDeltaLinkWrapper linkWrapper = Assert.IsType <ODataDeltaLinkWrapper>(e);
                Assert.Equal("Customers(32)", linkWrapper.DeltaLink.Source.OriginalString);
                Assert.Equal("Orders(10645)", linkWrapper.DeltaLink.Target.OriginalString);
                Assert.Equal("Orders", linkWrapper.DeltaLink.Relationship);
            });
        }
        public async Task ReadDeltaResourceSetWorksAsExpected()
        {
            // Arrange
            string payload = "{\"@context\":\"http://example.com/$metadata#Customers/$delta\"," +
                             "\"value\":[" +
                             "{" +
                             "\"@removed\":{\"reason\":\"changed\"}," +
                             "\"CustomerID\":1," +
                             "\"Orders@delta\":[" +
                             "{" +
                             "\"@removed\":{\"reason\":\"deleted\"}," +
                             "\"OrderId\":10" +
                             "}," +
                             "{" +
                             "\"@type\":\"#NS.VipOrder\"," +
                             "\"OrderId\":9," +
                             "\"Email\":\"[email protected]\"" +
                             "}" +
                             "]" +
                             "}" +
                             "]" +
                             "}";

            IEdmEntitySet customers = Model.EntityContainer.FindEntitySet("Customers");

            Assert.NotNull(customers); // Guard

            // Act
            Func <ODataMessageReader, Task <ODataReader> > func = mr => mr.CreateODataDeltaResourceSetReaderAsync(customers, customers.EntityType());
            ODataItemWrapper item = await ReadPayloadAsync(payload, Model, func, ODataVersion.V401);

            // Assert
            Assert.NotNull(item);

            // --- DeltaResourceSet
            //      |--- DeleteResource (1)
            //          |--- NestedResourceInfo (1-1)
            //               |--- DeltaResourceSet
            //                     |--- DelteResource
            //                     |--- Normal Resource
            ODataDeltaResourceSetWrapper deltaResourceSet = Assert.IsType <ODataDeltaResourceSetWrapper>(item);
            ODataResourceBaseWrapper     resourceBase     = Assert.Single(deltaResourceSet.ResourceBases);
            ODataDeletedResourceWrapper  deletedResource  = Assert.IsType <ODataDeletedResourceWrapper>(resourceBase);

            Assert.Equal(DeltaDeletedEntryReason.Changed, deletedResource.DeletedResource.Reason);

            ODataNestedResourceInfoWrapper nestedResourceInfo = Assert.Single(deletedResource.NestedResourceInfos);

            Assert.Equal("Orders", nestedResourceInfo.NestedResourceInfo.Name);
            Assert.True(nestedResourceInfo.NestedResourceInfo.IsCollection);

            ODataDeltaResourceSetWrapper ordersDeltaResourceSet = Assert.IsType <ODataDeltaResourceSetWrapper>(nestedResourceInfo.NestedResourceSet);

            Assert.Equal(2, ordersDeltaResourceSet.ResourceBases.Count);
            ODataDeletedResourceWrapper deletedResource1 = Assert.IsType <ODataDeletedResourceWrapper>(ordersDeltaResourceSet.ResourceBases.ElementAt(0));

            Assert.Equal(DeltaDeletedEntryReason.Deleted, deletedResource1.DeletedResource.Reason);

            ODataResourceWrapper resource2 = Assert.IsType <ODataResourceWrapper>(ordersDeltaResourceSet.ResourceBases.ElementAt(1));

            Assert.Equal("NS.VipOrder", resource2.Resource.TypeName);
            Assert.Collection(resource2.Resource.Properties,
                              p =>
            {
                Assert.Equal("OrderId", p.Name);
                Assert.Equal(9, p.Value);
            },
                              p =>
            {
                Assert.Equal("Email", p.Name);
                Assert.Equal("*****@*****.**", p.Value);
            });
        }
        /// <summary>
        /// Deserializes the given <paramref name="deltaResourceSet"/> under the given <paramref name="readContext"/>.
        /// </summary>
        /// <param name="deltaResourceSet">The delta resource set to deserialize.</param>
        /// <param name="elementType">The element type.</param>
        /// <param name="readContext">The deserializer context.</param>
        /// <returns>The deserialized resource set object.</returns>
        public virtual IEnumerable ReadDeltaResourceSet(ODataDeltaResourceSetWrapper deltaResourceSet, IEdmStructuredTypeReference elementType, ODataDeserializerContext readContext)
        {
            if (deltaResourceSet == null)
            {
                throw Error.ArgumentNull(nameof(deltaResourceSet));
            }

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

            // Delta Items
            foreach (ODataItemWrapper itemWrapper in deltaResourceSet.DeltaItems)
            {
                // Deleted Link
                ODataDeltaDeletedLinkWrapper deletedLinkWrapper = itemWrapper as ODataDeltaDeletedLinkWrapper;
                if (deletedLinkWrapper != null)
                {
                    yield return(ReadDeltaDeletedLink(deletedLinkWrapper, elementType, readContext));
                }

                // Added Link
                ODataDeltaLinkWrapper deltaLinkWrapper = itemWrapper as ODataDeltaLinkWrapper;
                if (deltaLinkWrapper != null)
                {
                    yield return(ReadDeltaLink(deltaLinkWrapper, elementType, readContext));
                }

                // DeletedResource
                ODataDeletedResourceWrapper deletedResourceWrapper = itemWrapper as ODataDeletedResourceWrapper;
                if (deletedResourceWrapper != null)
                {
                    // TODO: deleted resource
                    yield return(null);
                }

                // Added resource or updated resource
                ODataResourceWrapper resourceWrapper = itemWrapper as ODataResourceWrapper;
                if (resourceWrapper != null)
                {
                    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));
                    }

                    IEdmTypeReference        edmTypeReference = actualType.ToEdmTypeReference(true);
                    ODataEdmTypeDeserializer deserializer     = DeserializerProvider.GetEdmTypeDeserializer(edmTypeReference);
                    if (deserializer == null)
                    {
                        throw new SerializationException(
                                  Error.Format(SRResources.TypeCannotBeDeserialized, edmTypeReference.FullName()));
                    }

                    // TODO: normal resource
                    // yield return deserializer.ReadInline(resourceWrapper, edmTypeReference, readContext);
                    if (readContext.IsDeltaOfT)
                    {
                        Type          elementClrType = readContext.Model.GetClrType(elementType);
                        Type          deltaType      = typeof(Deltas.Delta <>).MakeGenericType(elementClrType);
                        Deltas.IDelta delta          = Activator.CreateInstance(deltaType) as Deltas.IDelta;
                        yield return(delta);
                    }
                    else
                    {
                        yield return(new EdmDeltaResourceObject(actualType as IEdmEntityType));
                    }

                    continue;
                }
            }
        }