public void apply_to_should_assign_model_with_declared_api_versions_from_mapped_convention_and_attributes()
        {
            // arrange
            var controllerBuilder     = new ControllerApiVersionConventionBuilder(typeof(DecoratedController));
            var actionBuilder         = new ActionApiVersionConventionBuilder(controllerBuilder);
            var method                = typeof(DecoratedController).GetMethod(nameof(DecoratedController.Get));
            var attributes            = method.GetCustomAttributes().Cast <object>().ToArray();
            var actionModel           = new ActionModel(method, attributes);
            var empty                 = Enumerable.Empty <ApiVersion>();
            var controllerVersionInfo = new ControllerVersionInfo(empty, empty, empty, empty);

            actionModel.SetProperty(controllerVersionInfo);
            actionBuilder.MapToApiVersion(new ApiVersion(2, 0))
            .MapToApiVersion(new ApiVersion(3, 0));

            // act
            actionBuilder.ApplyTo(actionModel);

            // assert
            actionModel.GetProperty <ApiVersionModel>().ShouldBeEquivalentTo(
                new
            {
                IsApiVersionNeutral    = false,
                DeclaredApiVersions    = new[] { new ApiVersion(2, 0), new ApiVersion(3, 0) },
                SupportedApiVersions   = new ApiVersion[0],
                DeprecatedApiVersions  = new ApiVersion[0],
                ImplementedApiVersions = new ApiVersion[0]
            });
        }
        public void apply_to_should_assign_empty_model_without_api_versions_from_mapped_convention()
        {
            // arrange
            var controllerBuilder     = new ControllerApiVersionConventionBuilder(typeof(UndecoratedController));
            var actionBuilder         = new ActionApiVersionConventionBuilder(controllerBuilder);
            var method                = typeof(UndecoratedController).GetMethod(nameof(UndecoratedController.Get));
            var actionModel           = new ActionModel(method, new object[0]);
            var empty                 = Enumerable.Empty <ApiVersion>();
            var controllerVersionInfo = new ControllerVersionInfo(empty, empty, empty, empty);

            actionModel.SetProperty(controllerVersionInfo);

            // act
            actionBuilder.ApplyTo(actionModel);

            // assert
            actionModel.GetProperty <ApiVersionModel>().ShouldBeEquivalentTo(
                new
            {
                IsApiVersionNeutral    = false,
                DeclaredApiVersions    = new ApiVersion[0],
                SupportedApiVersions   = new ApiVersion[0],
                DeprecatedApiVersions  = new ApiVersion[0],
                ImplementedApiVersions = new ApiVersion[0]
            });
        }
        void ApplyActionConventions(ControllerModel controller, ControllerVersionInfo controllerVersionInfo)
        {
            Contract.Requires(controller != null);
            Contract.Requires(controllerVersionInfo != null);

            if (VersionNeutral)
            {
                ApplyNeutralModelToActions(controller);
            }
            else
            {
                MergeActionAttributesWithConventions(controller, controllerVersionInfo);
            }
        }
        private void ApplyActionConventions(ControllerModel controller, ControllerVersionInfo controllerVersionInfo)
        {
            Contract.Requires(controller != null);

            foreach (var action in controller.Actions)
            {
                var key           = action.ActionMethod;
                var actionBuilder = default(ActionApiVersionConventionBuilder <T>);

                action.SetProperty(controller);

                if (ActionBuilders.TryGetValue(key, out actionBuilder))
                {
                    action.SetProperty(controllerVersionInfo);
                    actionBuilder.ApplyTo(action);
                    action.SetProperty(default(ControllerVersionInfo));
                }
                else
                {
                    action.SetProperty(new ApiVersionModel(controller, action));
                }
            }
        }
        void MergeActionAttributesWithConventions(ControllerModel controller, ControllerVersionInfo controllerVersionInfo)
        {
            Contract.Requires(controller != null);
            Contract.Requires(controllerVersionInfo != null);

            foreach (var action in controller.Actions)
            {
                var key = action.ActionMethod;

                action.SetProperty(controller);

                if (TryGetConvention(key, out var actionConvention))
                {
                    action.SetProperty(controllerVersionInfo);
                    actionConvention.ApplyTo(action);
                    action.SetProperty(default(ControllerVersionInfo));
                }
                else
                {
                    action.SetProperty(new ApiVersionModel(controller, action));
                }
            }
        }