MyTested.AspNetCore.Mvc icon indicating copy to clipboard operation
MyTested.AspNetCore.Mvc copied to clipboard

Generic dependencies are not automatically resolved

Open TonyTroeff opened this issue 4 years ago • 0 comments

Describe your issue Following your tutorial, I am registering all the necessary services in StartUp and TestStartup as well. However, they are generic and I believe that there is some problem with their resolving because it simply does not work out for me.

Project files This is the generic controller feature provider we have configured.

    public class GenericControllerFeatureProvider : IApplicationFeatureProvider<ControllerFeature>
    {
        private readonly string _entityIdType;

        public GenericControllerFeatureProvider(IConfiguration runningConfiguration)
        {
            if (runningConfiguration == null)
                throw new ArgumentNullException(nameof(runningConfiguration));

            this._entityIdType = runningConfiguration["EntityIdType"];

            if (string.IsNullOrWhiteSpace(this._entityIdType))
                throw new Exception(ExceptionMessages.YouMustSpecifyEntityIdTypeInAppsettings);
        }

        public void PopulateFeature(IEnumerable<ApplicationPart> applicationParts, ControllerFeature controllerFeature)
        {
            var publicTypes = typeof(GenericControllerFeatureProvider).Assembly.GetExportedTypes();
            var baseControllerType = typeof(IMyGenericController<>);

            var genericControllers =
                publicTypes.Where(
                        t => t.ContainsGenericParameters
                            && t.IsClass
                            && t.GetInterfaces().Any(i => i.IsGenericType && i.GetGenericTypeDefinition() == baseControllerType))
                    .ToList();

            Type[] typeArgs = { Type.GetType(this._entityIdType) };

            foreach (var genericController in genericControllers)
            {
                var genericType = genericController.MakeGenericType(typeArgs).GetTypeInfo();
                controllerFeature.Controllers.Add(genericType);
            }
        }
    }

This controller model convention is used to beautify the controller name if it is displayed in Swagger dor example.

    public class GenericControllerAttribute : Attribute, IControllerModelConvention
    {
        public void Apply(ControllerModel controller)
        {
            if (controller is null)
                throw new ArgumentNullException(nameof(controller));

            if (string.IsNullOrWhiteSpace(controller.ControllerName))
                return;

            var controllerName = controller.ControllerName;
            var characterIndex = controllerName.IndexOf("Controller`", StringComparison.InvariantCultureIgnoreCase);

            if (characterIndex >= 1)
            {
                var controllerTypeName = controllerName.Substring(0, characterIndex);
                controller.ControllerName = controllerTypeName;
            }
        }
    }

Startup classes This is the TestStartup class - nothing special.

    public class TestStartup : Quantum.DMS.API.Startup
    {
        public TestStartup(IConfiguration configuration)
            : base(configuration)
        {
        }

        public void ConfigureTestServices(IServiceCollection services)
        {
            base.ConfigureServices(services);
        }
    }

Expected behavior Calling a controller action without .Withdependencies(...) should work appropriately - take services internally from ASP and pass them to the requested controller's constructor)

Environment:

  • OS: Windows 10
  • ASP.NET Core Version 3.1

TonyTroeff avatar Jun 22 '20 21:06 TonyTroeff