コード例 #1
0
        public void CanCreateActionWithComplexReturnType()
        {
            // Arrange
            // Act
            ODataModelBuilder builder = new ODataModelBuilder();

            ActionConfiguration createAddress   = builder.Action("CreateAddress").Returns <Address>();
            ActionConfiguration createAddresses = builder.Action("CreateAddresses").ReturnsCollection <Address>();

            // Assert
            ComplexTypeConfiguration address = createAddress.ReturnType as ComplexTypeConfiguration;

            Assert.NotNull(address);
            Assert.Equal(typeof(Address).FullName, address.FullName);
            Assert.Null(createAddress.NavigationSource);

            CollectionTypeConfiguration addresses = createAddresses.ReturnType as CollectionTypeConfiguration;

            Assert.NotNull(addresses);
            Assert.Equal(string.Format("Collection({0})", typeof(Address).FullName), addresses.FullName);
            address = addresses.ElementType as ComplexTypeConfiguration;
            Assert.NotNull(address);
            Assert.Equal(typeof(Address).FullName, address.FullName);
            Assert.Null(createAddresses.NavigationSource);
        }
コード例 #2
0
        public void CanCreateFunctionWithEntityReturnType()
        {
            // Arrange & Act
            ODataModelBuilder builder = new ODataModelBuilder();

            FunctionConfiguration createGoodCustomer = builder.Function("CreateGoodCustomer").ReturnsFromEntitySet <Customer>("GoodCustomers");
            FunctionConfiguration createBadCustomers = builder.Function("CreateBadCustomers").ReturnsCollectionFromEntitySet <Customer>("BadCustomers");

            // Assert
            EntityTypeConfiguration customer = createGoodCustomer.ReturnType as EntityTypeConfiguration;

            Assert.NotNull(customer);
            Assert.Equal(typeof(Customer).FullName, customer.FullName);
            EntitySetConfiguration goodCustomers = builder.EntitySets.SingleOrDefault(s => s.Name == "GoodCustomers");

            Assert.NotNull(goodCustomers);
            Assert.Same(createGoodCustomer.NavigationSource, goodCustomers);

            CollectionTypeConfiguration customers = createBadCustomers.ReturnType as CollectionTypeConfiguration;

            Assert.NotNull(customers);
            customer = customers.ElementType as EntityTypeConfiguration;
            Assert.NotNull(customer);
            EntitySetConfiguration badCustomers = builder.EntitySets.SingleOrDefault(s => s.Name == "BadCustomers");

            Assert.NotNull(badCustomers);
            Assert.Same(createBadCustomers.NavigationSource, badCustomers);
        }
コード例 #3
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
                {
                    throw Error.InvalidOperation(SRResources.NoMatchingIEdmTypeFound, configuration.FullName);
                }
            }
        }
コード例 #4
0
        private static void AddOperationLinkBuilder(IEdmModel model, IEdmOperation operation, OperationConfiguration operationConfiguration)
        {
            Contract.Assert(model != null);
            ActionConfiguration   actionConfiguration = operationConfiguration as ActionConfiguration;
            IEdmAction            action = operation as IEdmAction;
            FunctionConfiguration functionConfiguration = operationConfiguration as FunctionConfiguration;
            IEdmFunction          function = operation as IEdmFunction;

            if (operationConfiguration.BindingParameter.TypeConfiguration.Kind == EdmTypeKind.Entity)
            {
                //if (actionConfiguration != null && actionConfiguration.GetActionLink() != null && action != null)
                //{
                //    model.SetOperationLinkBuilder(
                //        action,
                //        new OperationLinkBuilder(actionConfiguration.GetActionLink(), actionConfiguration.FollowsConventions));
                //}
                //else if (functionConfiguration != null && functionConfiguration.GetFunctionLink() != null && function != null)
                //{
                //    model.SetOperationLinkBuilder(
                //        function,
                //        new OperationLinkBuilder(functionConfiguration.GetFunctionLink(), functionConfiguration.FollowsConventions));
                //}
            }
            else if (operationConfiguration.BindingParameter.TypeConfiguration.Kind == EdmTypeKind.Collection)
            {
                CollectionTypeConfiguration collectionTypeConfiguration =
                    (CollectionTypeConfiguration)operationConfiguration.BindingParameter.TypeConfiguration;

                if (collectionTypeConfiguration.ElementType.Kind == EdmTypeKind.Entity)
                {
                    //if (actionConfiguration != null && actionConfiguration.GetFeedActionLink() != null && action != null)
                    //{
                    //    model.SetOperationLinkBuilder(
                    //        action,
                    //        new OperationLinkBuilder(actionConfiguration.GetFeedActionLink(), actionConfiguration.FollowsConventions));
                    //}
                    //else if (functionConfiguration != null && functionConfiguration.GetFeedFunctionLink() != null && function != null)
                    //{
                    //    model.SetOperationLinkBuilder(
                    //        function,
                    //        new OperationLinkBuilder(functionConfiguration.GetFeedFunctionLink(), functionConfiguration.FollowsConventions));
                    //}
                }
            }
        }
コード例 #5
0
 private static void AddParameter(
     ODataConventionModelBuilder builder,
     OperationConfiguration configuration,
     Type pType,
     string name)
 {
     if (pType.IsPrimitiveType())
     {
         var primitiveType = builder.AddPrimitiveType(pType);
         configuration.AddParameter(name, primitiveType);
     }
     else
     {
         if (pType.IsCollection())
         {
             if (pType.GenericTypeArguments[0].GetTypeInfo()
                 .IsPrimitive)
             {
                 var parameterType = builder.AddPrimitiveType(
                     pType.GenericTypeArguments[0]);
                 var collectionTypeConfig = new CollectionTypeConfiguration(
                     parameterType,
                     pType.GenericTypeArguments[0]);
                 configuration.AddParameter(name, collectionTypeConfig);
             }
             else
             {
                 var parameterType = builder.AddEntityType(
                     pType.GenericTypeArguments[0]);
                 var collectionTypeConfig = new CollectionTypeConfiguration(
                     parameterType,
                     pType.GenericTypeArguments[0]);
                 configuration.AddParameter(name, collectionTypeConfig);
             }
         }
         else
         {
             var parameterType = builder.AddEntityType(pType);
             configuration.AddParameter(name, parameterType);
         }
     }
 }
コード例 #6
0
        public void NonbindingParameterConfigurationSupportsParameterCollectionTypeAs(Type type, bool isNullable)
        {
            // Arrange
            ODataModelBuilder builder = new ODataModelBuilder();

            builder.EntityType <Customer>();
            builder.ComplexType <Address>();
            builder.EnumType <Color>();

            Type elementType;

            Assert.True(TypeHelper.IsCollection(type, out elementType));

            // Act
            Type underlyingType = TypeHelper.GetUnderlyingTypeOrSelf(elementType);
            IEdmTypeConfiguration       elementTypeConfiguration = builder.GetTypeConfigurationOrNull(underlyingType);
            CollectionTypeConfiguration collectionType           = new CollectionTypeConfiguration(elementTypeConfiguration,
                                                                                                   typeof(IEnumerable <>).MakeGenericType(elementType));

            NonbindingParameterConfiguration parameter = new NonbindingParameterConfiguration("name", collectionType);

            // Assert
            Assert.Equal(isNullable, parameter.Nullable);
        }
コード例 #7
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());
        }
コード例 #8
0
        public void CanBuildOperationBoundToCollectionCacheForIEdmModel()
        {
            // Arrange
            ODataModelBuilder builder = new ODataModelBuilder();
            EntityTypeConfiguration <Customer> customer = builder.EntitySet <Customer>("Customers").EntityType;

            customer.HasKey(c => c.ID);
            customer.Property(c => c.Name);
            customer.ComplexProperty(c => c.Address);

            EntityTypeConfiguration <Movie> movie = builder.EntitySet <Movie>("Movies").EntityType;

            movie.HasKey(m => m.ID);
            movie.HasKey(m => m.Name);
            EntityTypeConfiguration <Blockbuster> blockBuster = builder.EntityType <Blockbuster>().DerivesFrom <Movie>();
            EntityTypeConfiguration movieConfiguration        = builder.StructuralTypes.OfType <EntityTypeConfiguration>().Single(t => t.Name == "Movie");

            // build actions that are bindable to the collection of entity
            customer.Collection.Action("CollectionCustomerActionInCache1");
            customer.Collection.Action("CollectionCustomerActionInCache2");
            movie.Collection.Action("CollectionMovieActionInCache3");

            ActionConfiguration         movieActionIncache4     = builder.Action("CollectionMovieActionInCache4");
            CollectionTypeConfiguration collectionConfiguration = new CollectionTypeConfiguration(movieConfiguration, typeof(Movie));

            movieActionIncache4.SetBindingParameter("bindingParameter", collectionConfiguration);

            blockBuster.Collection.Action("CollectionBlockbusterActionInCache5");

            // build functions that are bindable to the collection of entity
            customer.Collection.Function("CollectionCustomerFunctionInCache1").Returns <int>();
            customer.Collection.Function("CollectionCustomerFunctionInCache2").Returns <int>();
            movie.Collection.Function("CollectionMovieFunctionInCache3").Returns <int>();
            blockBuster.Collection.Function("CollectionBlockbusterFunctionInCache5").Returns <int>();

            // build actions that are either: bindable to an entity, have no parameter, have only complex parameter
            customer.Action("CustomersActionNotInCache1");
            customer.Function("CustomersFunctionNotInCache1").Returns <int>();
            movie.Action("MoviesActionNotInCache2");
            builder.Action("NoParametersNotInCache3");

            ActionConfiguration addressParameterNotInCache4 = builder.Action("AddressParameterNotInCache4");

            addressParameterNotInCache4.Parameter <Address>("address");

            IEdmModel model = builder.GetEdmModel();

            IEdmEntityType customerType    = model.SchemaElements.OfType <IEdmEntityType>().Single(e => e.Name == "Customer");
            IEdmEntityType movieType       = model.SchemaElements.OfType <IEdmEntityType>().Single(e => e.Name == "Movie");
            IEdmEntityType blockBusterType = model.SchemaElements.OfType <IEdmEntityType>().Single(e => e.Name == "Blockbuster");

            // Act
            BindableOperationFinder annotation = new BindableOperationFinder(model);
            var movieOperations       = annotation.FindOperationsBoundToCollection(movieType).ToArray();
            var customerOperations    = annotation.FindOperationsBoundToCollection(customerType).ToArray();
            var blockBusterOperations = annotation.FindOperationsBoundToCollection(blockBusterType).ToArray();

            // Assert
            Assert.Equal(3, movieOperations.Length);
            Assert.Single(movieOperations.Where(a => a.Name == "CollectionMovieActionInCache3"));
            Assert.Single(movieOperations.Where(a => a.Name == "CollectionMovieActionInCache4"));
            Assert.Single(movieOperations.Where(a => a.Name == "CollectionMovieFunctionInCache3"));

            Assert.Equal(4, customerOperations.Length);
            Assert.Single(customerOperations.Where(a => a.Name == "CollectionCustomerActionInCache1"));
            Assert.Single(customerOperations.Where(a => a.Name == "CollectionCustomerActionInCache2"));
            Assert.Single(customerOperations.Where(a => a.Name == "CollectionCustomerFunctionInCache1"));
            Assert.Single(customerOperations.Where(a => a.Name == "CollectionCustomerFunctionInCache2"));

            Assert.Equal(5, blockBusterOperations.Length);
            Assert.Single(blockBusterOperations.Where(a => a.Name == "CollectionBlockbusterActionInCache5"));
            Assert.Single(blockBusterOperations.Where(a => a.Name == "CollectionBlockbusterFunctionInCache5"));
            Assert.Single(blockBusterOperations.Where(a => a.Name == "CollectionMovieActionInCache3"));
            Assert.Single(blockBusterOperations.Where(a => a.Name == "CollectionMovieActionInCache4"));
            Assert.Single(blockBusterOperations.Where(a => a.Name == "CollectionMovieFunctionInCache3"));
        }
コード例 #9
0
        private static void MapODataControllerActions(ODataConventionModelBuilder builder, Type ctrlType, EntityTypeConfiguration entityTypeConfig, EntitySetConfiguration entitySetConfig)
        {
            // Map actions
            var methods = ctrlType.GetMethods().Where(m => m.GetCustomAttribute <ODataProcedureAttribute>() != null);

            foreach (var method in methods)
            {
                var attr = method.GetCustomAttribute <ODataProcedureAttribute>();
                ProcedureConfiguration procedure;

                // TODO: Extract into separate class if possible
                Func <string, IEdmTypeConfiguration, ProcedureConfiguration> setBindingParameterFunc;

                string previousNamespace = builder.Namespace;
                builder.Namespace = attr.Namespace;

                if (attr.Type == ODataProcedureType.Action)
                {
                    // Create an action
                    procedure = builder.Action(attr.ProcedureName ?? method.Name);
                    setBindingParameterFunc = ((ActionConfiguration)procedure).SetBindingParameter;
                }
                else
                {
                    // Create a function
                    procedure = builder.Function(attr.ProcedureName ?? method.Name);
                    setBindingParameterFunc = ((FunctionConfiguration)procedure).SetBindingParameter;
                }

                builder.Namespace = previousNamespace;

                if (attr.Target == ODataProcedureTarget.Entity)
                {
                    // Bind to entity
                    setBindingParameterFunc(BindingParameterConfiguration.DefaultBindingParameterName, entityTypeConfig);
                }
                else
                {
                    // Bind to collection
                    var entityCollectionConfig = new CollectionTypeConfiguration(entityTypeConfig, typeof(Enumerable));
                    setBindingParameterFunc(BindingParameterConfiguration.DefaultBindingParameterName, entityCollectionConfig);
                }

                var parameterAttrs = method.GetCustomAttributes <ODataProcedureParameterAttribute>();
                foreach (var parameterAttr in parameterAttrs)
                {
                    var parameterType = parameterAttr.Type;

                    // Is the parameter type a collection?
                    if (parameterType.IsGenericType && parameterType.GetInterface(typeof(IEnumerable).Name, false) != null)
                    {
                        // If the parameter is a collection, we need to call the generic CollectionParameter<T>(name) method
                        var genericArgument = parameterType.GetGenericArguments().Single();

                        var parameterMethod = procedure.GetType().GetMethod("CollectionParameter");
                        var methodInfo      = parameterMethod.MakeGenericMethod(genericArgument);
                        methodInfo.Invoke(procedure, new object[] { parameterAttr.Name });
                    }
                    else
                    {
                        // If the parameter is not a collection, we call the generic Parameter<T>(name) method
                        var parameterMethod = procedure.GetType().GetMethod("Parameter");
                        var methodInfo      = parameterMethod.MakeGenericMethod(parameterType);
                        methodInfo.Invoke(procedure, new object[] { parameterAttr.Name });
                    }
                }

                if (attr.Returns != null)
                {
                    var returns = procedure.GetType().GetMethod("Returns");
                    var generic = returns.MakeGenericMethod(attr.Returns);
                    generic.Invoke(procedure, null);
                }
                else if (attr.ReturnsCollection != null)
                {
                    var returnsCollection = procedure.GetType().GetMethod("ReturnsCollection");
                    var generic           = returnsCollection.MakeGenericMethod(attr.ReturnsCollection);
                    generic.Invoke(procedure, null);
                }
                else if (attr.ReturnsEntity != null)
                {
                    var returnsEntity = procedure.GetType().GetMethod("ReturnsFromEntitySet", new Type[] { typeof(string) });
                    var generic       = returnsEntity.MakeGenericMethod(attr.ReturnsEntity);

                    var entitySet = builder.EntitySets.Single(set => set.ClrType == attr.ReturnsEntity);
                    generic.Invoke(procedure, new object[] { entitySet.Name });
                }
                else if (attr.ReturnsEntityCollection != null)
                {
                    var returnsEntity = procedure.GetType().GetMethod("ReturnsCollectionFromEntitySet", new Type[] { typeof(string) });
                    var generic       = returnsEntity.MakeGenericMethod(attr.ReturnsEntityCollection);

                    var entitySet = builder.EntitySets.Single(set => set.ClrType == attr.ReturnsEntityCollection);
                    generic.Invoke(procedure, new object[] { entitySet.Name });
                }
                else
                {
                    procedure.ReturnType = builder.GetTypeConfigurationOrNull(method.ReturnType);
                }
            }
        }