internal IEdmType ResolveExpectedTypeForReading(Type clientClrType) { Debug.Assert(clientClrType != null, "materializerType != null"); ClientTypeAnnotation clientTypeAnnotation = this.clientEdmModel.GetClientTypeAnnotation(clientClrType); clientTypeAnnotation.EnsureEPMLoaded(); IEdmType clientType = clientTypeAnnotation.EdmType; if (this.serviceModel == null) { return(clientType); } // for primitive types there is no need for the server's metadata if (clientType.TypeKind == EdmTypeKind.Primitive) { return(clientType); } if (clientType.TypeKind == EdmTypeKind.Collection) { IEdmTypeReference clientEdmElementType = ((IEdmCollectionType)clientType).ElementType; if (clientEdmElementType.IsPrimitive()) { return(clientType); } var elementType = clientClrType.GetGenericArguments()[0]; var elementEdmType = this.ResolveExpectedTypeForReading(elementType); if (elementEdmType == null) { // If we can't determine an expected element type, for whatever reason, then we cannot construct an expected collection type. // This was introduced to fix SQLBU TFS Bug 1227624: Query for collection of complex values fails on JSON client when type-name resolver is not defined. return(null); } return(new EdmCollectionType(elementEdmType.ToEdmTypeReference(clientEdmElementType.IsNullable))); } IEdmStructuredType serverType; if (!this.TryToResolveServerType(clientTypeAnnotation, out serverType)) { // if we don't know the server type, but do have a server model, then simply read without an expected type. return(null); } return(serverType); }
internal IEdmType ResolveWireTypeName(IEdmType expectedEdmType, string wireName) { Type elementType; ClientEdmModel model = ClientEdmModel.GetModel(this.ResponseInfo.MaxProtocolVersion); if (expectedEdmType != null) { ClientTypeAnnotation annotation = model.GetClientTypeAnnotation(expectedEdmType); elementType = annotation.ElementType; if (annotation.EdmType.TypeKind == EdmTypeKind.Primitive) { return(expectedEdmType); } } else { elementType = typeof(object); } Type type2 = this.ResolveTypeFromName(wireName, elementType); ClientTypeAnnotation clientTypeAnnotation = model.GetClientTypeAnnotation(model.GetOrCreateEdmType(type2)); if (clientTypeAnnotation.IsEntityType) { clientTypeAnnotation.EnsureEPMLoaded(); } switch (clientTypeAnnotation.EdmType.TypeKind) { case EdmTypeKind.Entity: case EdmTypeKind.Complex: { string key = clientTypeAnnotation.EdmType.FullName(); if (!this.edmTypeNameMap.ContainsKey(key)) { this.edmTypeNameMap.Add(key, clientTypeAnnotation); } break; } } return(clientTypeAnnotation.EdmType); }
/// <summary> /// ODL callback for client type resolution /// </summary> /// <param name="expectedEdmType">The expected type for the given wire name</param> /// <param name="wireName">The name of the type from the payload</param> /// <returns>An IEdmType</returns> internal IEdmType ResolveWireTypeName(IEdmType expectedEdmType, string wireName) { // ODataLib should never pass an empty or null type name Debug.Assert(!String.IsNullOrEmpty(wireName), "!String.IsNullOrEmpty(wireName)"); // For V3 and above, ODataLib will never call the type resolver if there is a collection // type specified in the wire. However, in V1/V2, since there was no collection feature // supported, it will call us with a collection wire name, but its okay to return null // in that case, since there is no collection supported. If the user writes the type // resolver in such a way to handle collections themselver, even then it will fail later // in ODataLib stating collection types are not supported in V1/V2 versions. if (expectedEdmType != null) { // In V1/V2, we never used to call the type resolver for primitives types. // Instead, we just used to look at the expected property type and try to convert // the value from the payload to the expected property type. In other words, we // used to ignore the type name on the wire for primitive properties. if (expectedEdmType.TypeKind == EdmTypeKind.Primitive) { return(expectedEdmType); } } Type expectedType; if (expectedEdmType != null) { ClientTypeAnnotation expectedAnnotation = this.clientEdmModel.GetClientTypeAnnotation(expectedEdmType); Debug.Assert(expectedAnnotation != null, "expectedAnnotation != null"); expectedType = expectedAnnotation.ElementType; } else { expectedType = typeof(object); } // Breaking change: 353786 - we decided to validate against the resolved type if the type are not assignable. Type resolvedType = this.ResolveTypeFromName(wireName, expectedType); ClientTypeAnnotation resolvedTypeAnnotation = this.clientEdmModel.GetClientTypeAnnotation(this.clientEdmModel.GetOrCreateEdmType(resolvedType)); Debug.Assert(resolvedTypeAnnotation != null, "result != null -- otherwise ClientType.Create returned null"); if (resolvedTypeAnnotation.IsEntityType) { resolvedTypeAnnotation.EnsureEPMLoaded(); } IEdmType clientEdmType = resolvedTypeAnnotation.EdmType; EdmTypeKind typeKind = clientEdmType.TypeKind; if (typeKind == EdmTypeKind.Entity || typeKind == EdmTypeKind.Complex) { // If the edm type name is not present in the dictionary, add it to the map string edmTypeName = clientEdmType.FullName(); if (!this.edmTypeNameMap.ContainsKey(edmTypeName)) { this.edmTypeNameMap.Add(edmTypeName, resolvedTypeAnnotation); } } return(clientEdmType); }