private async Task WriteFeedAsync(IEnumerable enumerable, IEdmTypeReference feedType, ODataWriter writer,
                                          ODataSerializerContext writeContext)
        {
            Contract.Assert(writer != null);
            Contract.Assert(writeContext != null);
            Contract.Assert(enumerable != null);
            Contract.Assert(feedType != null);

            IEdmStructuredTypeReference elementType = GetResourceType(feedType);

            if (elementType.IsComplex())
            {
                ODataResourceSet resourceSet = new ODataResourceSet()
                {
                    TypeName = feedType.FullName()
                };

                await writer.WriteStartAsync(resourceSet).ConfigureAwait(false);

                ODataResourceSerializer entrySerializer = SerializerProvider.GetEdmTypeSerializer(elementType) as ODataResourceSerializer;
                if (entrySerializer == null)
                {
                    throw new SerializationException(
                              Error.Format(SRResources.TypeCannotBeSerialized, elementType.FullName()));
                }

                foreach (object entry in enumerable)
                {
                    await entrySerializer.WriteDeltaObjectInlineAsync(entry, elementType, writer, writeContext).ConfigureAwait(false);
                }
            }
            else
            {
                ODataDeltaResourceSet deltaFeed = CreateODataDeltaFeed(enumerable, feedType.AsCollection(), writeContext);
                if (deltaFeed == null)
                {
                    throw new SerializationException(Error.Format(SRResources.CannotSerializerNull, DeltaFeed));
                }

                // save the next page link for later to support JSON odata.streaming.
                Func <object, Uri> nextLinkGenerator = GetNextLinkGenerator(deltaFeed, enumerable, writeContext);
                deltaFeed.NextPageLink = null;

                //Start writing of the Delta Feed
                await writer.WriteStartAsync(deltaFeed).ConfigureAwait(false);

                object lastResource = null;
                //Iterate over all the entries present and select the appropriate write method.
                //Write method creates ODataDeltaDeletedEntry / ODataDeltaDeletedLink / ODataDeltaLink or ODataEntry.
                foreach (object entry in enumerable)
                {
                    if (entry == null)
                    {
                        throw new SerializationException(SRResources.NullElementInCollection);
                    }

                    lastResource = entry;
                    IEdmChangedObject edmChangedObject = entry as IEdmChangedObject;
                    if (edmChangedObject == null)
                    {
                        throw new SerializationException(Error.Format(
                                                             SRResources.CannotWriteType, GetType().Name, enumerable.GetType().FullName));
                    }

                    switch (edmChangedObject.DeltaKind)
                    {
                    case EdmDeltaEntityKind.DeletedEntry:
                        await WriteDeltaDeletedEntryAsync(entry, writer, writeContext).ConfigureAwait(false);

                        break;

                    case EdmDeltaEntityKind.DeletedLinkEntry:
                        await WriteDeltaDeletedLinkAsync(entry, writer, writeContext).ConfigureAwait(false);

                        break;

                    case EdmDeltaEntityKind.LinkEntry:
                        await WriteDeltaLinkAsync(entry, writer, writeContext).ConfigureAwait(false);

                        break;

                    case EdmDeltaEntityKind.Entry:
                    {
                        ODataResourceSerializer entrySerializer = SerializerProvider.GetEdmTypeSerializer(elementType) as ODataResourceSerializer;
                        if (entrySerializer == null)
                        {
                            throw new SerializationException(
                                      Error.Format(SRResources.TypeCannotBeSerialized, elementType.FullName()));
                        }
                        await entrySerializer.WriteDeltaObjectInlineAsync(entry, elementType, writer, writeContext)
                        .ConfigureAwait(false);

                        break;
                    }

                    default:
                        break;
                    }
                }

                // Subtle and surprising behavior: If the NextPageLink property is set before calling WriteStart(feed),
                // the next page link will be written early in a manner not compatible with odata.streaming=true. Instead, if
                // the next page link is not set when calling WriteStart(feed) but is instead set later on that feed
                // object before calling WriteEnd(), the next page link will be written at the end, as required for
                // odata.streaming=true support.

                deltaFeed.NextPageLink = nextLinkGenerator(lastResource);
            }

            //End Writing of the Delta Feed
            await writer.WriteEndAsync().ConfigureAwait(false);
        }