示例#1
0
        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);
        }
示例#2
0
        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);
        }
示例#3
0
        /// <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);
        }