private void ReadDeltaResourceSetInline(ODataDeltaResourceSetWrapper resourceSetWrapper, IEdmTypeReference edmType, ODataDeserializerContext readContext, out System.Collections.ICollection modifiedItems, out ICollection deletedItems) { Contract.Assert(resourceSetWrapper != null); Contract.Assert(edmType != null); Contract.Assert(readContext != null); IEdmModel model = readContext.Model; IEdmStructuredTypeReference structuredType = edmType.AsCollection().ElementType().AsStructured(); Type clrItemType = EdmLibHelpers.GetClrType(structuredType, model); Type deltaType = typeof(Delta <>).MakeGenericType(clrItemType); IList addedResult = (IList)Activator.CreateInstance(typeof(List <>).MakeGenericType(deltaType)); foreach (ODataResourceWrapper resourceItemWrapper in resourceSetWrapper.Resources) { IEnumerable <string> updatableProperties = GetUpdatableProperties(model, structuredType); Delta resourceItem = (Delta)Activator.CreateInstance(deltaType, clrItemType, updatableProperties); ApplyResourceProperties(resourceItem, resourceItemWrapper, structuredType, readContext); addedResult.Add(resourceItem); } modifiedItems = addedResult; IList deletedResult = (IList)Activator.CreateInstance(typeof(List <>).MakeGenericType(clrItemType)); foreach (ODataDeletedResourceWrapper deletedItem in resourceSetWrapper.DeletedResources) { object resourceItem = Activator.CreateInstance(clrItemType); ApplyResourceProperties(resourceItem, deletedItem, structuredType, readContext); deletedResult.Add(resourceItem); } deletedItems = deletedResult; }
private void ApplyDeltaResourceSetInNestedProperty(IEdmProperty nestedProperty, object resource, ODataDeltaResourceSetWrapper resourceSetWrapper, ODataDeserializerContext readContext) { Contract.Assert(nestedProperty != null); Contract.Assert(resource != null); Contract.Assert(readContext != null); if (!readContext.IsDeltaOfT) { throw new ODataException("Read context of @odata.delta incorrect"); } ICollection modifiedItems; ICollection deletedItems; ReadDeltaResourceSetInline(resourceSetWrapper, nestedProperty.Type, readContext, out modifiedItems, out deletedItems); IDelta resourceDelta = (IDelta)resource; string propertyName = EdmLibHelpers.GetClrPropertyName(nestedProperty, readContext.Model); resourceDelta.TrySetPropertyCollectionValue(propertyName, modifiedItems); resourceDelta.TrySetDeletedPropertyValue(propertyName, deletedItems); }
/// <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("resource"); } if (resourceInfoWrapper == null) { throw Error.ArgumentNull("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; } ODataDeltaResourceSetWrapper deltaResourceSetWrapper = childItem as ODataDeltaResourceSetWrapper; if (deltaResourceSetWrapper != null) { if (edmProperty != null) { ApplyDeltaResourceSetInNestedProperty(edmProperty, resource, deltaResourceSetWrapper, readContext); } // Note: we do not deal with dynamic resource 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); } } } }
private static void ReadCollectionItem(ODataReader reader, Stack <ODataItemBase> itemsStack, ref ODataItemBase topLevelItem) { switch (reader.State) { case ODataReaderState.ResourceStart: ODataResource resource = (ODataResource)reader.Item; ODataResourceWrapper resourceWrapper = null; if (resource != null) { resourceWrapper = new ODataResourceWrapper(resource); } if (itemsStack.Count == 0) { Contract.Assert(resource != null, "The top-level resource can never be null."); topLevelItem = resourceWrapper; } else { ODataItemBase parentItem = itemsStack.Peek(); ODataResourceSetWrapper parentResourceSet = parentItem as ODataResourceSetWrapper; if (parentResourceSet != null) { parentResourceSet.Resources.Add(resourceWrapper); } else { ODataNestedResourceInfoWrapper parentNestedResource = parentItem as ODataNestedResourceInfoWrapper; if (parentNestedResource != null) { Contract.Assert(parentNestedResource.NestedResourceInfo.IsCollection == false, "Only singleton nested properties can contain resource as their child."); Contract.Assert(parentNestedResource.NestedItems.Count == 0, "Each nested property can contain only one resource as its direct child."); parentNestedResource.NestedItems.Add(resourceWrapper); } else { ODataDeltaResourceSetWrapper parentDeltaSetResource = (ODataDeltaResourceSetWrapper)parentItem; parentDeltaSetResource.Resources.Add(resourceWrapper); } } } itemsStack.Push(resourceWrapper); break; case ODataReaderState.ResourceEnd: Contract.Assert( itemsStack.Count > 0 && (reader.Item == null || itemsStack.Peek().Item == reader.Item), "The resource which is ending should be on the top of the items stack."); itemsStack.Pop(); break; case ODataReaderState.NestedResourceInfoStart: ODataNestedResourceInfo nestedResourceInfo = (ODataNestedResourceInfo)reader.Item; Contract.Assert(nestedResourceInfo != null, "nested resource info should never be null."); ODataNestedResourceInfoWrapper nestedResourceInfoWrapper = new ODataNestedResourceInfoWrapper(nestedResourceInfo); Contract.Assert(itemsStack.Count > 0, "nested resource info can't appear as top-level item."); { ODataResourceWrapper parentResource = (ODataResourceWrapper)itemsStack.Peek(); parentResource.NestedResourceInfos.Add(nestedResourceInfoWrapper); } itemsStack.Push(nestedResourceInfoWrapper); break; case ODataReaderState.NestedResourceInfoEnd: Contract.Assert(itemsStack.Count > 0 && itemsStack.Peek().Item == reader.Item, "The nested resource info which is ending should be on the top of the items stack."); itemsStack.Pop(); break; case ODataReaderState.ResourceSetStart: ODataResourceSet resourceSet = (ODataResourceSet)reader.Item; Contract.Assert(resourceSet != null, "ResourceSet should never be null."); ODataResourceSetWrapper resourceSetWrapper = new ODataResourceSetWrapper(resourceSet); if (itemsStack.Count > 0) { ODataNestedResourceInfoWrapper parentNestedResourceInfo = (ODataNestedResourceInfoWrapper)itemsStack.Peek(); Contract.Assert(parentNestedResourceInfo != null, "this has to be an inner resource set. inner resource sets always have a nested resource info."); Contract.Assert(parentNestedResourceInfo.NestedResourceInfo.IsCollection == true, "Only collection nested properties can contain resource set as their child."); parentNestedResourceInfo.NestedItems.Add(resourceSetWrapper); } else { topLevelItem = resourceSetWrapper; } itemsStack.Push(resourceSetWrapper); break; case ODataReaderState.ResourceSetEnd: Contract.Assert(itemsStack.Count > 0 && itemsStack.Peek().Item == reader.Item, "The resource set which is ending should be on the top of the items stack."); itemsStack.Pop(); break; case ODataReaderState.EntityReferenceLink: ODataEntityReferenceLink entityReferenceLink = (ODataEntityReferenceLink)reader.Item; Contract.Assert(entityReferenceLink != null, "Entity reference link should never be null."); ODataEntityReferenceLinkBase entityReferenceLinkWrapper = new ODataEntityReferenceLinkBase(entityReferenceLink); Contract.Assert(itemsStack.Count > 0, "Entity reference link should never be reported as top-level item."); { ODataNestedResourceInfoWrapper parentNavigationLink = (ODataNestedResourceInfoWrapper)itemsStack.Peek(); parentNavigationLink.NestedItems.Add(entityReferenceLinkWrapper); } break; case ODataReaderState.DeltaResourceSetStart: ODataDeltaResourceSet deltaResourceSet = (ODataDeltaResourceSet)reader.Item; Contract.Assert(deltaResourceSet != null, "ResourceSet should never be null."); ODataDeltaResourceSetWrapper deltaResourceSetWrapper = new ODataDeltaResourceSetWrapper(deltaResourceSet); if (itemsStack.Count > 0) { ODataNestedResourceInfoWrapper parentNestedResourceInfo = (ODataNestedResourceInfoWrapper)itemsStack.Peek(); Contract.Assert(parentNestedResourceInfo != null, "this has to be an inner resource set. inner resource sets always have a nested resource info."); Contract.Assert(parentNestedResourceInfo.NestedResourceInfo.IsCollection == true, "Only collection nested properties can contain resource set as their child."); parentNestedResourceInfo.NestedItems.Add(deltaResourceSetWrapper); } else { topLevelItem = deltaResourceSetWrapper; } itemsStack.Push(deltaResourceSetWrapper); break; case ODataReaderState.DeltaResourceSetEnd: Contract.Assert(itemsStack.Count > 0 && itemsStack.Peek().Item == reader.Item, "The resource set which is ending should be on the top of the items stack."); itemsStack.Pop(); break; case ODataReaderState.DeletedResourceStart: ODataDeletedResource deletedResource = (ODataDeletedResource)reader.Item; if (deletedResource != null) { // Note: I expect that deleted resourced will not have other nested resources ODataDeletedResourceWrapper deletedResourceWrapper = new ODataDeletedResourceWrapper(deletedResource); ODataItemBase parentItem = itemsStack.Peek(); ODataDeltaResourceSetWrapper parentDeltaSetResource = parentItem as ODataDeltaResourceSetWrapper; if (parentDeltaSetResource != null) { parentDeltaSetResource.DeletedResources.Add(deletedResourceWrapper); } } break; case ODataReaderState.DeletedResourceEnd: break; default: Contract.Assert(false, "We should never get here, it means the ODataReader reported a wrong state."); break; } }