/// <summary> /// Validates that the expected primitive type 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) { DebugUtils.CheckNoExternalCallers(); Debug.Assert(expectedTypeReference != null && expectedTypeReference.IsODataPrimitiveTypeKind(), "expectedTypeReference must be a primitive type."); Debug.Assert(typeReferenceFromValue != null && typeReferenceFromValue.IsODataPrimitiveTypeKind(), "typeReferenceFromValue must be a primitive type."); IEdmPrimitiveType expectedType = (IEdmPrimitiveType)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.ODataFullName(), typeReferenceFromValue.IsNullable, expectedTypeReference.ODataFullName(), expectedTypeReference.IsNullable)); } }
internal static void ValidateMetadataPrimitiveType(IEdmTypeReference expectedTypeReference, IEdmTypeReference typeReferenceFromValue) { IEdmPrimitiveType definition = (IEdmPrimitiveType)expectedTypeReference.Definition; IEdmPrimitiveType subtype = (IEdmPrimitiveType)typeReferenceFromValue.Definition; bool flag = ((expectedTypeReference.IsNullable == typeReferenceFromValue.IsNullable) || (expectedTypeReference.IsNullable && !typeReferenceFromValue.IsNullable)) || !typeReferenceFromValue.IsODataValueType(); bool flag2 = definition.IsAssignableFrom(subtype); if (!flag || !flag2) { throw new ODataException(Microsoft.Data.OData.Strings.ValidationUtils_IncompatiblePrimitiveItemType(typeReferenceFromValue.ODataFullName(), typeReferenceFromValue.IsNullable, expectedTypeReference.ODataFullName(), expectedTypeReference.IsNullable)); } }
internal static IEdmPrimitiveType GetCommonBaseType(this IEdmPrimitiveType firstType, IEdmPrimitiveType secondType) { IEdmPrimitiveType type; if (((IEdmType)firstType).IsEquivalentTo((IEdmType)secondType)) { return(firstType); } for (type = firstType; type != null; type = type.BaseType()) { if (type.IsAssignableFrom(secondType)) { return(type); } } for (type = secondType; type != null; type = type.BaseType()) { if (type.IsAssignableFrom(firstType)) { return(type); } } return(null); }
/// <summary> /// Checks if the <paramref name="firstType"/> primitive type and the <paramref name="secondType"/> primitive type /// have a common base type. /// In other words, if <paramref name="secondType"/> is a subtype of <paramref name="firstType"/> or not. /// </summary> /// <param name="firstType">Type of the base type.</param> /// <param name="secondType">Type of the sub type.</param> /// <returns>The common base type or null if no common base type exists.</returns> internal static IEdmPrimitiveType GetCommonBaseType(this IEdmPrimitiveType firstType, IEdmPrimitiveType secondType) { DebugUtils.CheckNoExternalCallers(); Debug.Assert(firstType != null, "firstType != null"); Debug.Assert(secondType != null, "secondType != null"); if (firstType.IsEquivalentTo(secondType)) { return firstType; } IEdmPrimitiveType commonBaseType = firstType; while (commonBaseType != null) { if (commonBaseType.IsAssignableFrom(secondType)) { return commonBaseType; } commonBaseType = commonBaseType.BaseType(); } commonBaseType = secondType; while (commonBaseType != null) { if (commonBaseType.IsAssignableFrom(firstType)) { return commonBaseType; } commonBaseType = commonBaseType.BaseType(); } return null; }
/// <summary> /// Determines if a <paramref name="sourcePrimitiveType"/> is convertibale according to OData rules to the /// <paramref name="targetPrimitiveType"/>. /// </summary> /// <param name="sourceNodeOrNull">The node which is to be converted.</param> /// <param name="sourcePrimitiveType">The type which is to be converted.</param> /// <param name="targetPrimitiveType">The type to which we want to convert.</param> /// <returns>true if the source type is convertible to the target type; otherwise false.</returns> internal static bool CanConvertPrimitiveTypeTo( SingleValueNode sourceNodeOrNull, IEdmPrimitiveType sourcePrimitiveType, IEdmPrimitiveType targetPrimitiveType) { Debug.Assert(sourcePrimitiveType != null, "sourcePrimitiveType != null"); Debug.Assert(targetPrimitiveType != null, "targetPrimitiveType != null"); EdmPrimitiveTypeKind sourcePrimitiveKind = sourcePrimitiveType.PrimitiveKind; EdmPrimitiveTypeKind targetPrimitiveKind = targetPrimitiveType.PrimitiveKind; switch (sourcePrimitiveKind) { case EdmPrimitiveTypeKind.SByte: switch (targetPrimitiveKind) { case EdmPrimitiveTypeKind.SByte: case EdmPrimitiveTypeKind.Int16: case EdmPrimitiveTypeKind.Int32: case EdmPrimitiveTypeKind.Int64: case EdmPrimitiveTypeKind.Single: case EdmPrimitiveTypeKind.Double: case EdmPrimitiveTypeKind.Decimal: return(true); } break; case EdmPrimitiveTypeKind.Byte: switch (targetPrimitiveKind) { case EdmPrimitiveTypeKind.Byte: case EdmPrimitiveTypeKind.Int16: case EdmPrimitiveTypeKind.Int32: case EdmPrimitiveTypeKind.Int64: case EdmPrimitiveTypeKind.Single: case EdmPrimitiveTypeKind.Double: case EdmPrimitiveTypeKind.Decimal: return(true); } break; case EdmPrimitiveTypeKind.Int16: switch (targetPrimitiveKind) { case EdmPrimitiveTypeKind.Int16: case EdmPrimitiveTypeKind.Int32: case EdmPrimitiveTypeKind.Int64: case EdmPrimitiveTypeKind.Single: case EdmPrimitiveTypeKind.Double: case EdmPrimitiveTypeKind.Decimal: return(true); } break; case EdmPrimitiveTypeKind.Int32: switch (targetPrimitiveKind) { case EdmPrimitiveTypeKind.Int32: case EdmPrimitiveTypeKind.Int64: case EdmPrimitiveTypeKind.Single: case EdmPrimitiveTypeKind.Double: case EdmPrimitiveTypeKind.Decimal: return(true); } break; case EdmPrimitiveTypeKind.Int64: switch (targetPrimitiveKind) { case EdmPrimitiveTypeKind.Int64: case EdmPrimitiveTypeKind.Single: case EdmPrimitiveTypeKind.Double: case EdmPrimitiveTypeKind.Decimal: return(true); } break; case EdmPrimitiveTypeKind.Single: switch (targetPrimitiveKind) { case EdmPrimitiveTypeKind.Single: case EdmPrimitiveTypeKind.Double: return(true); // allow single constant->decimal in order to made L,M,D,F optional case EdmPrimitiveTypeKind.Decimal: object tmp; return(TryGetConstantNodePrimitiveLDMF(sourceNodeOrNull, out tmp)); } break; case EdmPrimitiveTypeKind.Double: switch (targetPrimitiveKind) { case EdmPrimitiveTypeKind.Double: return(true); // allow double constant->decimal in order to made L,M,D,F optional // (if the double value actually has overflowed decimal.MaxValue, exception will occur later. more details in ExpressionLexer.cs) case EdmPrimitiveTypeKind.Decimal: object tmp; return(TryGetConstantNodePrimitiveLDMF(sourceNodeOrNull, out tmp)); } break; default: return(sourcePrimitiveKind == targetPrimitiveKind || targetPrimitiveType.IsAssignableFrom(sourcePrimitiveType)); } return(false); }
/// <summary> /// Determines if a <paramref name="sourcePrimitiveType"/> is convertibale according to OData rules to the /// <paramref name="targetPrimitiveType"/>. /// </summary> /// <param name="sourcePrimitiveType">The type which is to be converted.</param> /// <param name="targetPrimitiveType">The type to which we want to convert.</param> /// <returns>true if the source type is convertible to the target type; otherwise false.</returns> internal static bool CanConvertPrimitiveTypeTo( IEdmPrimitiveType sourcePrimitiveType, IEdmPrimitiveType targetPrimitiveType) { DebugUtils.CheckNoExternalCallers(); Debug.Assert(sourcePrimitiveType != null, "sourcePrimitiveType != null"); Debug.Assert(targetPrimitiveType != null, "targetPrimitiveType != null"); EdmPrimitiveTypeKind sourcePrimitiveKind = sourcePrimitiveType.PrimitiveKind; EdmPrimitiveTypeKind targetPrimitiveKind = targetPrimitiveType.PrimitiveKind; switch (sourcePrimitiveKind) { case EdmPrimitiveTypeKind.SByte: switch (targetPrimitiveKind) { case EdmPrimitiveTypeKind.SByte: case EdmPrimitiveTypeKind.Int16: case EdmPrimitiveTypeKind.Int32: case EdmPrimitiveTypeKind.Int64: case EdmPrimitiveTypeKind.Single: case EdmPrimitiveTypeKind.Double: case EdmPrimitiveTypeKind.Decimal: return(true); } break; case EdmPrimitiveTypeKind.Byte: switch (targetPrimitiveKind) { case EdmPrimitiveTypeKind.Byte: case EdmPrimitiveTypeKind.Int16: case EdmPrimitiveTypeKind.Int32: case EdmPrimitiveTypeKind.Int64: case EdmPrimitiveTypeKind.Single: case EdmPrimitiveTypeKind.Double: case EdmPrimitiveTypeKind.Decimal: return(true); } break; case EdmPrimitiveTypeKind.Int16: switch (targetPrimitiveKind) { case EdmPrimitiveTypeKind.Int16: case EdmPrimitiveTypeKind.Int32: case EdmPrimitiveTypeKind.Int64: case EdmPrimitiveTypeKind.Single: case EdmPrimitiveTypeKind.Double: case EdmPrimitiveTypeKind.Decimal: return(true); } break; case EdmPrimitiveTypeKind.Int32: switch (targetPrimitiveKind) { case EdmPrimitiveTypeKind.Int32: case EdmPrimitiveTypeKind.Int64: case EdmPrimitiveTypeKind.Single: case EdmPrimitiveTypeKind.Double: case EdmPrimitiveTypeKind.Decimal: return(true); } break; case EdmPrimitiveTypeKind.Int64: switch (targetPrimitiveKind) { case EdmPrimitiveTypeKind.Int64: case EdmPrimitiveTypeKind.Single: case EdmPrimitiveTypeKind.Double: case EdmPrimitiveTypeKind.Decimal: return(true); } break; case EdmPrimitiveTypeKind.Single: switch (targetPrimitiveKind) { case EdmPrimitiveTypeKind.Single: case EdmPrimitiveTypeKind.Double: return(true); } break; default: return(sourcePrimitiveKind == targetPrimitiveKind || targetPrimitiveType.IsAssignableFrom(sourcePrimitiveType)); } return(false); }
internal static IEdmPrimitiveType GetCommonBaseType(this IEdmPrimitiveType firstType, IEdmPrimitiveType secondType) { IEdmPrimitiveType type; if (((IEdmType) firstType).IsEquivalentTo((IEdmType) secondType)) { return firstType; } for (type = firstType; type != null; type = type.BaseType()) { if (type.IsAssignableFrom(secondType)) { return type; } } for (type = secondType; type != null; type = type.BaseType()) { if (type.IsAssignableFrom(firstType)) { return type; } } return null; }
/// <summary> /// Determines if a <paramref name="sourcePrimitiveType"/> is convertibale according to OData rules to the /// <paramref name="targetPrimitiveType"/>. /// </summary> /// <param name="sourceNodeOrNull">The node which is to be converted.</param> /// <param name="sourcePrimitiveType">The type which is to be converted.</param> /// <param name="targetPrimitiveType">The type to which we want to convert.</param> /// <returns>true if the source type is convertible to the target type; otherwise false.</returns> internal static bool CanConvertPrimitiveTypeTo( SingleValueNode sourceNodeOrNull, IEdmPrimitiveType sourcePrimitiveType, IEdmPrimitiveType targetPrimitiveType) { Debug.Assert(sourcePrimitiveType != null, "sourcePrimitiveType != null"); Debug.Assert(targetPrimitiveType != null, "targetPrimitiveType != null"); EdmPrimitiveTypeKind sourcePrimitiveKind = sourcePrimitiveType.PrimitiveKind; EdmPrimitiveTypeKind targetPrimitiveKind = targetPrimitiveType.PrimitiveKind; switch (sourcePrimitiveKind) { case EdmPrimitiveTypeKind.SByte: switch (targetPrimitiveKind) { case EdmPrimitiveTypeKind.SByte: case EdmPrimitiveTypeKind.Int16: case EdmPrimitiveTypeKind.Int32: case EdmPrimitiveTypeKind.Int64: case EdmPrimitiveTypeKind.Single: case EdmPrimitiveTypeKind.Double: case EdmPrimitiveTypeKind.Decimal: return true; } break; case EdmPrimitiveTypeKind.Byte: switch (targetPrimitiveKind) { case EdmPrimitiveTypeKind.Byte: case EdmPrimitiveTypeKind.Int16: case EdmPrimitiveTypeKind.Int32: case EdmPrimitiveTypeKind.Int64: case EdmPrimitiveTypeKind.Single: case EdmPrimitiveTypeKind.Double: case EdmPrimitiveTypeKind.Decimal: return true; } break; case EdmPrimitiveTypeKind.Int16: switch (targetPrimitiveKind) { case EdmPrimitiveTypeKind.Int16: case EdmPrimitiveTypeKind.Int32: case EdmPrimitiveTypeKind.Int64: case EdmPrimitiveTypeKind.Single: case EdmPrimitiveTypeKind.Double: case EdmPrimitiveTypeKind.Decimal: return true; } break; case EdmPrimitiveTypeKind.Int32: switch (targetPrimitiveKind) { case EdmPrimitiveTypeKind.Int32: case EdmPrimitiveTypeKind.Int64: case EdmPrimitiveTypeKind.Single: case EdmPrimitiveTypeKind.Double: case EdmPrimitiveTypeKind.Decimal: return true; } break; case EdmPrimitiveTypeKind.Int64: switch (targetPrimitiveKind) { case EdmPrimitiveTypeKind.Int64: case EdmPrimitiveTypeKind.Single: case EdmPrimitiveTypeKind.Double: case EdmPrimitiveTypeKind.Decimal: return true; } break; case EdmPrimitiveTypeKind.Single: switch (targetPrimitiveKind) { case EdmPrimitiveTypeKind.Single: case EdmPrimitiveTypeKind.Double: return true; // allow single constant->decimal in order to made L,M,D,F optional case EdmPrimitiveTypeKind.Decimal: object tmp; return TryGetConstantNodePrimitiveLDMF(sourceNodeOrNull, out tmp); } break; case EdmPrimitiveTypeKind.Double: switch (targetPrimitiveKind) { case EdmPrimitiveTypeKind.Double: return true; // allow double constant->decimal in order to made L,M,D,F optional // (if the double value actually has overflowed decimal.MaxValue, exception will occur later. more details in ExpressionLexer.cs) case EdmPrimitiveTypeKind.Decimal: object tmp; return TryGetConstantNodePrimitiveLDMF(sourceNodeOrNull, out tmp); } break; case EdmPrimitiveTypeKind.DateTimeOffset: switch (targetPrimitiveKind) { case EdmPrimitiveTypeKind.DateTimeOffset: return true; case EdmPrimitiveTypeKind.Date: object tmp; return TryGetConstantNodePrimitiveDate(sourceNodeOrNull, out tmp); } break; default: return sourcePrimitiveKind == targetPrimitiveKind || targetPrimitiveType.IsAssignableFrom(sourcePrimitiveType); } return false; }