/// <summary> /// Reads a value from the message reader. /// </summary> /// <param name="expectedClientType">The expected client type being materialized into.</param> /// <param name="expectedReaderType">The expected type for the underlying reader.</param> protected override void ReadWithExpectedType(IEdmTypeReference expectedClientType, IEdmTypeReference expectedReaderType) { if (!expectedClientType.IsCollection()) { throw new DataServiceClientException(DSClient.Strings.AtomMaterializer_TypeShouldBeCollectionError(expectedClientType.FullName())); } Type underlyingExpectedType = Nullable.GetUnderlyingType(this.ExpectedType) ?? this.ExpectedType; Debug.Assert(WebUtil.IsCLRTypeCollection(underlyingExpectedType, this.MaterializerContext.Model) || (SingleResult.HasValue && !SingleResult.Value), "expected type must be collection or single result must be false"); // We are here for two cases: // (1) Something like Execute<ICollection<T>>, in which case the underlyingExpectedType is ICollection<T> // (2) Execute<T> with the bool singleValue = false, in which case underlyingExpectedType is T Type collectionItemType = underlyingExpectedType; Type collectionICollectionType = ClientTypeUtil.GetImplementationType(underlyingExpectedType, typeof(ICollection <>)); if (collectionICollectionType != null) { // Case 1 : Something like Execute<ICollection<T>>, in which case the underlyingExpectedType is ICollection<T> collectionItemType = collectionICollectionType.GetGenericArguments()[0]; } else { // Case 2 : Execute<T> with the bool singleValue = false, in which case underlyingExpectedType is T collectionICollectionType = typeof(ICollection <>).MakeGenericType(new Type[] { collectionItemType }); } Type clrCollectionType = WebUtil.GetBackingTypeForCollectionProperty(collectionICollectionType); object collectionInstance = this.CollectionValueMaterializationPolicy.CreateCollectionInstance((IEdmCollectionTypeReference)expectedClientType, clrCollectionType); // Enumerator over our collection reader was created, then ApplyDataCollections was refactored to // take an enumerable instead of a ODataCollectionValue. Enumerator is being used as a bridge ODataCollectionReader collectionReader = messageReader.CreateODataCollectionReader(); NonEntityItemsEnumerable collectionEnumerable = new NonEntityItemsEnumerable(collectionReader); bool isElementNullable = expectedClientType.AsCollection().ElementType().IsNullable; this.CollectionValueMaterializationPolicy.ApplyCollectionDataValues( collectionEnumerable, null /*wireTypeName*/, collectionInstance, collectionItemType, ClientTypeUtil.GetAddToCollectionDelegate(collectionICollectionType), isElementNullable); this.currentValue = collectionInstance; }
/// <summary> /// Reads a value from the message reader. /// </summary> /// <param name="expectedClientType">The expected client type being materialized into.</param> /// <param name="expectedReaderType">The expected type for the underlying reader.</param> protected override void ReadWithExpectedType(IEdmTypeReference expectedClientType, IEdmTypeReference expectedReaderType) { if (!expectedClientType.IsCollection()) { throw new DataServiceClientException(DSClient.Strings.AtomMaterializer_TypeShouldBeCollectionError(expectedClientType.FullName())); } Type underlyingExpectedType = Nullable.GetUnderlyingType(this.ExpectedType) ?? this.ExpectedType; bool isClrCollection = WebUtil.IsCLRTypeCollection(underlyingExpectedType, this.MaterializerContext.Model); Debug.Assert(isClrCollection || (SingleResult.HasValue && !SingleResult.Value), "expected type must be collection or single result must be false"); // We are here for two cases: // (1) Something like Execute<ICollection<T>>, in which case the underlyingExpectedType is ICollection<T> // (2) Execute<T> with the bool singleValue = false, in which case underlyingExpectedType is T Type collectionItemType = underlyingExpectedType; Type collectionICollectionType = ClientTypeUtil.GetImplementationType(underlyingExpectedType, typeof(ICollection<>)); if (collectionICollectionType != null) { // Case 1 : Something like Execute<ICollection<T>>, in which case the underlyingExpectedType is ICollection<T> collectionItemType = collectionICollectionType.GetGenericArguments()[0]; } else { // Case 2 : Execute<T> with the bool singleValue = false, in which case underlyingExpectedType is T collectionICollectionType = typeof(ICollection<>).MakeGenericType(new Type[] { collectionItemType }); } Type clrCollectionType = WebUtil.GetBackingTypeForCollectionProperty(collectionICollectionType, collectionItemType); object collectionInstance = this.CollectionValueMaterializationPolicy.CreateCollectionInstance((IEdmCollectionTypeReference)expectedClientType, clrCollectionType); // Enumerator over our collection reader was created, then ApplyDataCollections was refactored to // take an enumerable instead of a ODataCollectionValue. Enumerator is being used as a bridge ODataCollectionReader collectionReader = messageReader.CreateODataCollectionReader(); NonEntityItemsEnumerable collectionEnumerable = new NonEntityItemsEnumerable(collectionReader); bool isElementNullable = expectedClientType.AsCollection().ElementType().IsNullable; this.CollectionValueMaterializationPolicy.ApplyCollectionDataValues( collectionEnumerable, null /*wireTypeName*/, collectionInstance, collectionItemType, ClientTypeUtil.GetAddToCollectionDelegate(collectionICollectionType), isElementNullable); this.currentValue = collectionInstance; }