/// <summary> /// Validates that the expected primitive type or type definition matches the actual primitive type. /// </summary> /// <param name="expectedTypeReference">The expected type.</param> /// <param name="typeReferenceFromValue">The actual type.</param> internal static void ValidateMetadataPrimitiveType(IEdmTypeReference expectedTypeReference, IEdmTypeReference typeReferenceFromValue) { Debug.Assert(expectedTypeReference != null && (expectedTypeReference.IsODataPrimitiveTypeKind() || expectedTypeReference.IsODataTypeDefinitionTypeKind()), "expectedTypeReference must be a primitive type or type definition."); Debug.Assert(typeReferenceFromValue != null && typeReferenceFromValue.IsODataPrimitiveTypeKind(), "typeReferenceFromValue must be a primitive type."); IEdmType expectedType = expectedTypeReference.Definition; IEdmPrimitiveType typeFromValue = (IEdmPrimitiveType)typeReferenceFromValue.Definition; // The two primitive types match if they have the same definition and either both or only the // expected type is nullable // NOTE: for strings and binary values we must not check nullability here because the type reference // from the value is always nullable since C# has no way to express non-nullable strings. // However, this codepath is only hit if the value is not 'null' so we can assign a non-null // value to both nullable and non-nullable string/binary types. bool nullableCompatible = expectedTypeReference.IsNullable == typeReferenceFromValue.IsNullable || expectedTypeReference.IsNullable && !typeReferenceFromValue.IsNullable || !MetadataUtilsCommon.IsODataValueType(typeReferenceFromValue); bool typeCompatible = expectedType.IsAssignableFrom(typeFromValue); if (!nullableCompatible || !typeCompatible) { // incompatible type name for value! throw new ODataException(Strings.ValidationUtils_IncompatiblePrimitiveItemType( typeReferenceFromValue.FullName(), typeReferenceFromValue.IsNullable, expectedTypeReference.FullName(), expectedTypeReference.IsNullable)); } }