/// <summary> /// Gets or creates an <see cref="IEdmCollectionType"/> for the <paramref name="itemResourceType"/>. /// </summary> /// <param name="collectionResourceType">The collection resource type that the edm type is being created from.</param> /// <param name="itemResourceType">The item resource type to create an EDM collection type for.</param> /// <param name="customAnnotations">The optional annotations for the resource type; the annotations can contain facets that need to be applied to the type reference.</param> /// <returns>An <see cref="IEdmCollectionType"/> instance for the <paramref name="itemResourceType"/> item type.</returns> /// <remarks> /// Materialization state: none required. No change in materialization state. /// Cache state: none required. No change in cache state. /// </remarks> private IEdmCollectionType EnsureCollectionItemTypeIsPrimitiveOrComplex(CollectionResourceType collectionResourceType, ResourceType itemResourceType, List<KeyValuePair<string, object>> customAnnotations) { Debug.Assert(itemResourceType != null, "itemResourceType != null"); IEdmCollectionType collectionType; if (this.primitiveOrComplexCollectionTypeCache.TryGetValue(itemResourceType, out collectionType)) { return collectionType; } IEdmTypeReference elementTypeReference; switch (itemResourceType.ResourceTypeKind) { case ResourceTypeKind.ComplexType: // WCF DS forces the item types of collection types to not be nullable. Only starting v3, can complex properties be nullable. // For providers, like reflection providers, we need to ensure complex items continue to be non-nullable. elementTypeReference = this.EnsureTypeReference(itemResourceType, customAnnotations); elementTypeReference = elementTypeReference.IsNullable != PrimitiveOrComplexCollectionItemTypeDefaultNullability ? elementTypeReference.Clone(PrimitiveOrComplexCollectionItemTypeDefaultNullability) : elementTypeReference; break; case ResourceTypeKind.Primitive: // WCF DS forces the item types of collection types to not be nullable MetadataProviderUtils.GetAndRemoveNullableFacet(customAnnotations); IEdmPrimitiveTypeReference primitiveTypeReference = MetadataProviderUtils.CreatePrimitiveTypeReference(itemResourceType, customAnnotations); elementTypeReference = primitiveTypeReference.IsNullable != PrimitiveOrComplexCollectionItemTypeDefaultNullability ? primitiveTypeReference.Clone(PrimitiveOrComplexCollectionItemTypeDefaultNullability) : primitiveTypeReference; break; case ResourceTypeKind.EntityType: // fall through case ResourceTypeKind.Collection: // fall through case ResourceTypeKind.EntityCollection: // fall through default: throw new InvalidOperationException(Microsoft.OData.Service.Strings.MetadataProviderEdmModel_UnsupportedCollectionItemType_PrimitiveOrComplex(itemResourceType.ResourceTypeKind.ToString())); } collectionType = new MetadataProviderEdmCollectionType(collectionResourceType, elementTypeReference); this.primitiveOrComplexCollectionTypeCache.Add(itemResourceType, collectionType); return collectionType; }
/// <summary>Creates a server value from a client value.</summary> /// <param name="value">The value to convert.</param> /// <param name="resourceType">The resource type of the value.</param> /// <param name="createCollection">Optional func to create a new collection instance on the server. /// The first parameter is the collection resource type, the second is enumeration of server items to be added to the collection.</param> /// <param name="clientInstanceToResourceType">Func to resolve client resource to a server resource type.</param> /// <returns>The server representation of the client value</returns> public static object CreateServerValueFromClientValue( object value, providers.ResourceType resourceType, Func <providers.CollectionResourceType, IEnumerable <object>, object> createCollection, Func <object, providers.ResourceType> clientInstanceToResourceType) { if (value == null) { return(null); } Type valueType = value.GetType(); if (valueType.IsValueType || (valueType.IsGenericParameter && valueType.GetGenericTypeDefinition() == typeof(Nullable <>)) || value is string) { // Primitive value return(value); } else if (value is IEnumerable) { // Collection providers.CollectionResourceType collectionResourceType = (providers.CollectionResourceType)resourceType; object collection = null; List <object> serverItems = new List <object>(); foreach (object item in (IEnumerable)value) { serverItems.Add(CreateServerValueFromClientValue( item, collectionResourceType == null ? null : collectionResourceType.ItemType, createCollection, clientInstanceToResourceType)); } if (createCollection != null) { collection = createCollection(collectionResourceType, serverItems); } if (collection == null) { Type itemType = collectionResourceType == null? TypeSystem.GetIEnumerableElementType(value.GetType()) : collectionResourceType.ItemType.InstanceType; if (itemType == null) { throw new Exception("Can't determine the item type of an open collection property."); } Type listType = typeof(List <>).MakeGenericType(itemType); object serverItemsConverted = typeof(Enumerable).GetMethod("Cast").MakeGenericMethod(itemType).Invoke(null, new object[] { serverItems }); collection = Activator.CreateInstance(listType, serverItemsConverted); } return(collection); } else { // Complex type return(CreateServerResourceFromClientResource(value, createCollection, clientInstanceToResourceType)); } }
/// <summary>Returns a read-only version of the specified collection.</summary> /// <param name="collection">The collection to convert to read-only.</param> /// <param name="resourceType">The resourceType of this collection property.</param> /// <returns>A read-only collection.</returns> internal static object GetReadOnlyCollection(IList collection, CollectionResourceType resourceType) { Debug.Assert(collection.GetType() == typeof(List<object>), "The collection was not created by CreateNewCollectionProperty."); return new CollectionPropertyValueEnumerable(collection, resourceType); }
protected override void BeginCollectionPropertyValue(CollectionResourceType CollectionResourceType) { // { this.writer.StartObjectScope(); // __metadata : { Type : "typename" } this.writer.WriteName(JsonMetadataString); this.writer.StartObjectScope(); this.writer.WriteName(JsonTypeString); this.writer.WriteValue(CollectionResourceType.FullName); this.writer.EndScope(); // "results": this.writer.WriteDataArrayName(); // [ this.writer.StartArrayScope(); }
protected override void BeginCollectionPropertyValue(CollectionResourceType CollectionResourceType) { // Do nothing }
protected abstract void BeginCollectionPropertyValue(CollectionResourceType CollectionResourceType);