/// <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)); } }
internal static IEdmOperation[] CalculateBindableOperationsForType(IEdmType bindingType, IEdmModel model, EdmTypeResolver edmTypeResolver) { Debug.Assert(model != null, "model != null"); Debug.Assert(edmTypeResolver != null, "edmTypeResolver != null"); List <IEdmOperation> operations = null; try { operations = model.FindBoundOperations(bindingType).ToList(); } catch (Exception exc) { if (!ExceptionUtils.IsCatchableExceptionType(exc)) { throw; } throw new ODataException(Strings.MetadataUtils_CalculateBindableOperationsForType(bindingType.FullTypeName()), exc); } List <IEdmOperation> operationsFound = new List <IEdmOperation>(); foreach (IEdmOperation operation in operations.EnsureOperationsBoundWithBindingParameter()) { IEdmOperationParameter bindingParameter = operation.Parameters.FirstOrDefault(); IEdmType resolvedBindingType = edmTypeResolver.GetParameterType(bindingParameter).Definition; if (resolvedBindingType.IsAssignableFrom(bindingType)) { operationsFound.Add(operation); } } return(operationsFound.ToArray()); }
/// <summary> /// Calculates the operations that are always bindable to the given type. /// </summary> /// <param name="bindingType">The binding type in question.</param> /// <param name="model">The model to search for operations.</param> /// <param name="edmTypeResolver">The edm type resolver to get the parameter type.</param> /// <returns>An enumeration of operations that are always bindable to the given type.</returns> internal static IEdmFunctionImport[] CalculateAlwaysBindableOperationsForType(IEdmType bindingType, IEdmModel model, EdmTypeResolver edmTypeResolver) { DebugUtils.CheckNoExternalCallers(); Debug.Assert(model != null, "model != null"); Debug.Assert(edmTypeResolver != null, "edmTypeResolver != null"); List <IEdmFunctionImport> operations = new List <IEdmFunctionImport>(); foreach (IEdmEntityContainer container in model.EntityContainers()) { foreach (IEdmFunctionImport functionImport in container.FunctionImports()) { if (!functionImport.IsBindable || !model.IsAlwaysBindable(functionImport)) { continue; } IEdmFunctionParameter bindingParameter = functionImport.Parameters.FirstOrDefault(); if (bindingParameter == null) { continue; } IEdmType resolvedBindingType = edmTypeResolver.GetParameterType(bindingParameter).Definition; if (resolvedBindingType.IsAssignableFrom(bindingType)) { operations.Add(functionImport); } } } return(operations.ToArray()); }
/// <summary> /// Parse from levelsOption token to LevelsClause. /// Negative value would be treated as max. /// </summary> /// <param name="levelsOption">The levelsOption for current expand.</param> /// <param name="sourceType">The type of current level navigation source.</param> /// <param name="property">Navigation property for current expand.</param> /// <returns>The LevelsClause parsed, null if levelsOption is null</returns> private LevelsClause ParseLevels(long?levelsOption, IEdmType sourceType, IEdmNavigationProperty property) { if (!levelsOption.HasValue) { return(null); } IEdmType relatedType = property.ToEntityType(); if (sourceType != null && relatedType != null && !sourceType.IsAssignableFrom(relatedType)) { throw new ODataException(ODataErrorStrings.ExpandItemBinder_LevelsNotAllowedOnIncompatibleRelatedType(property.Name, sourceType.ODataFullName(), relatedType.ODataFullName())); } return(new LevelsClause(levelsOption.Value < 0, levelsOption.Value)); }
/// <summary> /// Calculates the operations that are bindable to the given type. /// </summary> /// <param name="bindingType">The binding type in question.</param> /// <param name="model">The model to search for operations.</param> /// <param name="edmTypeResolver">The edm type resolver to get the parameter type.</param> /// <returns>An enumeration of operations that are always bindable to the given type.</returns> internal static IList <IEdmOperation> CalculateBindableOperationsForType(IEdmType bindingType, IEdmModel model, EdmTypeResolver edmTypeResolver) { Debug.Assert(model != null, "model != null"); Debug.Assert(edmTypeResolver != null, "edmTypeResolver != null"); IEnumerable <IEdmOperation> operations = null; try { operations = model.FindBoundOperations(bindingType); } catch (Exception exc) { if (!ExceptionUtils.IsCatchableExceptionType(exc)) { throw; } throw new ODataException(Strings.MetadataUtils_CalculateBindableOperationsForType(bindingType.FullTypeName()), exc); } List <IEdmOperation> operationsFound = new List <IEdmOperation>(); foreach (IEdmOperation operation in operations) { if (!operation.IsBound) { throw new ODataException(Strings.EdmLibraryExtensions_UnBoundOperationsFoundFromIEdmModelFindMethodIsInvalid(operation.Name)); } if (operation.Parameters.FirstOrDefault() == null) { throw new ODataException(Strings.EdmLibraryExtensions_NoParameterBoundOperationsFoundFromIEdmModelFindMethodIsInvalid(operation.Name)); } IEdmOperationParameter bindingParameter = operation.Parameters.FirstOrDefault(); IEdmType resolvedBindingType = edmTypeResolver.GetParameterType(bindingParameter).Definition; if (resolvedBindingType.IsAssignableFrom(bindingType)) { operationsFound.Add(operation); } } return(operationsFound); }