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); } }
/// <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)); } }
/// <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); }
/// <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); }
/// <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); } }
/// <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); }
/// <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; } } }
/// <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); }
/// <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); } }
/// <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); } }
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)); }
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); }
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); } }
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; }
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); }
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); }
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)); }