예제 #1
0
        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);
                }
            }
        }
예제 #2
0
        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) { }
                        }
                    }
                }
            }
        }