private static IEdmTypeReference GetEdmTypeReference(Dictionary <Type, IEdmType> availableTypes, IEdmTypeConfiguration configuration, bool nullable) { Contract.Assert(availableTypes != null); if (configuration == null) { return(null); } EdmTypeKind kind = configuration.Kind; if (kind == EdmTypeKind.Collection) { CollectionTypeConfiguration collectionType = (CollectionTypeConfiguration)configuration; EdmCollectionType edmCollectionType = new EdmCollectionType(GetEdmTypeReference(availableTypes, collectionType.ElementType, nullable)); return(new EdmCollectionTypeReference(edmCollectionType)); } else { Type configurationClrType = TypeHelper.GetUnderlyingTypeOrSelf(configuration.ClrType); if (!TypeHelper.IsEnum(configurationClrType)) { configurationClrType = configuration.ClrType; } IEdmType type; if (availableTypes.TryGetValue(configurationClrType, out type)) { if (kind == EdmTypeKind.Complex) { return(new EdmComplexTypeReference((IEdmComplexType)type, nullable)); } else if (kind == EdmTypeKind.Entity) { return(new EdmEntityTypeReference((IEdmEntityType)type, nullable)); } else if (kind == EdmTypeKind.Enum) { return(new EdmEnumTypeReference((IEdmEnumType)type, nullable)); } else { throw Error.InvalidOperation(SRResources.UnsupportedEdmTypeKind, kind.ToString()); } } else if (configuration.Kind == EdmTypeKind.Primitive) { PrimitiveTypeConfiguration primitiveTypeConfiguration = (PrimitiveTypeConfiguration)configuration; EdmPrimitiveTypeKind typeKind = EdmTypeBuilder.GetTypeKind(primitiveTypeConfiguration.ClrType); return(EdmCoreModel.Instance.GetPrimitive(typeKind, nullable)); } else if (configuration.Kind == EdmTypeKind.Untyped) { return(EdmCoreModel.Instance.GetUntyped()); } else { throw Error.InvalidOperation(SRResources.NoMatchingIEdmTypeFound, configuration.FullName); } } }
public static IEdmModel BuildEdmModel(Type ApiContextType) { ODataModelBuilder builder = new ODataConventionModelBuilder(); builder.Namespace = ApiContextType.Namespace; var publicProperties = ApiContextType.GetProperties(BindingFlags.Public | BindingFlags.Instance); foreach (var property in publicProperties) { var entityClrType = TypeHelper.GetImplementedIEnumerableType(property.PropertyType); EntityTypeConfiguration entity = builder.AddEntityType(entityClrType); builder.AddEntitySet(property.Name, entity); } // Get the actions and functions into the model var publicMethods = ApiContextType.GetMethods(BindingFlags.Public | BindingFlags.Instance); foreach (var method in publicMethods) { if (!method.IsSpecialName) { var entityClrType = TypeHelper.GetImplementedIEnumerableType(method.ReturnType) ?? method.ReturnType; OperationConfiguration configuration = null; PrimitiveTypeConfiguration primitiveEntityType = null; EntityTypeConfiguration entityType = null; if (entityClrType.GetTypeInfo().IsPrimitive || entityClrType.GetType() == typeof(decimal) || entityClrType.GetType() == typeof(string)) { primitiveEntityType = builder.AddPrimitiveType(entityClrType); } else { entityType = builder.AddEntityType(entityClrType); } var functionAttribute = method.GetCustomAttribute <ODataFunctionAttribute>(); if (functionAttribute != null) { configuration = builder.Function(method.Name); if (functionAttribute.IsBound) { configuration.SetBindingParameterImplementation(functionAttribute.BindingName, entityType); } } var actionAttribute = method.GetCustomAttribute <ODataActionAttribute>(); if (actionAttribute != null) { configuration = builder.Action(method.Name); if (actionAttribute.IsBound) { configuration.SetBindingParameterImplementation(actionAttribute.BindingName, entityType); } } if (configuration != null) { if (primitiveEntityType == null) { configuration.ReturnType = entityType; } else { configuration.ReturnType = primitiveEntityType; } configuration.IsComposable = true; configuration.NavigationSource = builder.NavigationSources.FirstOrDefault(n => n.EntityType == entityType) as NavigationSourceConfiguration; foreach (var parameterInfo in method.GetParameters()) { if (parameterInfo.ParameterType.GetTypeInfo().IsPrimitive || parameterInfo.ParameterType == typeof(decimal) || parameterInfo.ParameterType == typeof(string)) { var primitiveType = builder.AddPrimitiveType(parameterInfo.ParameterType); configuration.AddParameter(parameterInfo.Name, primitiveType); } else { if (parameterInfo.ParameterType.IsCollection()) { if (parameterInfo.ParameterType.GenericTypeArguments[0].GetTypeInfo().IsPrimitive) { var parameterType = builder.AddPrimitiveType(parameterInfo.ParameterType.GenericTypeArguments[0]); var collectionTypeConfig = new CollectionTypeConfiguration(parameterType, parameterInfo.ParameterType.GenericTypeArguments[0]); configuration.AddParameter(parameterInfo.Name, collectionTypeConfig); } else { var parameterType = builder.AddEntityType(parameterInfo.ParameterType.GenericTypeArguments[0]); var collectionTypeConfig = new CollectionTypeConfiguration(parameterType, parameterInfo.ParameterType.GenericTypeArguments[0]); configuration.AddParameter(parameterInfo.Name, collectionTypeConfig); } } else { var parameterType = builder.AddEntityType(parameterInfo.ParameterType); configuration.AddParameter(parameterInfo.Name, parameterType); } } } } } } return(builder.GetEdmModel()); }
private static void ApplyAttributes(IAssemblyProvider assemblyProvider, ODataConventionModelBuilder builder) { var allTypes = assemblyProvider.CandidateAssemblies.SelectMany(a => a.ExportedTypes); foreach (var type in allTypes) { if (type.IsAbstract) { continue; } MethodInfo[] publicMethods = null; try { publicMethods = type.GetMethods(BindingFlags.Public | BindingFlags.Instance); } catch (FileLoadException) { } if (publicMethods != null) { foreach (var method in publicMethods) { if (!method.IsSpecialName) { try { var functionAttribute = method.GetCustomAttribute <ODataFunctionAttribute>(); var actionAttribute = method.GetCustomAttribute <ODataActionAttribute>(); if (functionAttribute == null && actionAttribute == null) { var genericFunctionAttribute = method.GetCustomAttribute <ODataGenericFunctionAttribute>(); var genericActionAttribute = method.GetCustomAttribute <ODataGenericActionAttribute>(); if (genericActionAttribute == null && genericFunctionAttribute == null) { continue; } var genericTypeDefinition = method.DeclaringType.IsGenericTypeDefinition ? method.DeclaringType : method.DeclaringType.GetGenericTypeDefinition(); var genericArguments = genericTypeDefinition.GetGenericArguments(); var genericParameters = method.DeclaringType.GetGenericArguments(); Type GetTypeFromDefinition(string name) { if (string.IsNullOrWhiteSpace(name)) { return(null); } for (var i = 0; i < genericArguments.Length; i++) { if (genericArguments[i].Name == name) { return(genericParameters[i]); } } throw new ArgumentException( $"Unable to find generic parameter with name {name} on type {method.DeclaringType.Name}"); } if (genericFunctionAttribute != null) { functionAttribute = new ODataFunctionAttribute(); functionAttribute.IsBound = genericFunctionAttribute.IsBound; functionAttribute.BindingName = genericFunctionAttribute.BindingName; functionAttribute.ForCollection = GetTypeFromDefinition(genericFunctionAttribute .ForCollectionTypeParameterName); functionAttribute.ForType = GetTypeFromDefinition(genericFunctionAttribute .ForTypeTypeParameterName); } if (genericActionAttribute != null) { actionAttribute = new ODataActionAttribute(); actionAttribute.IsBound = genericActionAttribute.IsBound; actionAttribute.BindingName = genericActionAttribute.BindingName; actionAttribute.ForCollection = GetTypeFromDefinition(genericActionAttribute .ForCollectionTypeParameterName); actionAttribute.ForType = GetTypeFromDefinition(genericActionAttribute .ForTypeTypeParameterName); } } var entityClrType = TypeHelper.GetImplementedIEnumerableType(method.ReturnType) ?? method.ReturnType; entityClrType = entityClrType.UnwrapTask(); PrimitiveTypeConfiguration primitiveEntityType = null; EntityTypeConfiguration entityType = null; var isActionResult = typeof(IActionResult).IsAssignableFrom(entityClrType); if (!isActionResult) { if (entityClrType.IsPrimitiveType()) { primitiveEntityType = builder.AddPrimitiveType(entityClrType); } else { entityType = builder.AddEntityType(entityClrType); } } var configuration = ODataMethodBuilder.BuildMethod( method, builder, functionAttribute, actionAttribute, out var bindingName); if (configuration != null) { if (!isActionResult) { if (primitiveEntityType == null) { configuration.ReturnType = entityType; } else { configuration.ReturnType = primitiveEntityType; } } configuration.IsComposable = true; configuration.NavigationSource = builder.NavigationSources.FirstOrDefault(n => n.EntityType == entityType); foreach (var parameterInfo in method.GetParameters()) { if (!string.IsNullOrWhiteSpace(bindingName) && parameterInfo.Name == bindingName) { continue; } if (actionAttribute != null) { if (parameterInfo.GetCustomAttributes(typeof(FromBodyAttribute)) != null) { //if (parameterInfo.ParameterType.Name == "DummyModel") //{ // int a = 0; //} //if (parameterInfo.ParameterType.Name == "newParent") //{ // int a = 0; //} if (parameterInfo.ParameterType.IsPrimitiveType()) { AddParameter(builder, configuration, parameterInfo.ParameterType, parameterInfo.Name); } else if (builder.EntitySets.Any(t => t.ClrType == parameterInfo.ParameterType)) { AddParameter(builder, configuration, parameterInfo.ParameterType, parameterInfo.Name); } else { foreach (var property in parameterInfo.ParameterType .GetProperties()) { AddParameter(builder, configuration, property.PropertyType, property.Name); } } } } else { AddParameter(builder, configuration, parameterInfo.ParameterType, parameterInfo.Name); } } } } catch (FileLoadException) { } } } } } }