通用控制器未注册

时间:2019-04-03 22:06:41

标签: c# reflection dependency-injection .net-core

为我所有的通用控制器生成有效类型,并在ConfigureApplicationPartManager选项中调用PopulateFeature方法,但是当我尝试实现GenericControllerRouteConvention时,该控制器不在已注册控制器的列表中。

  var providerTypes = new List<Type>();
            var refAssemblies = Assembly.GetExecutingAssembly().GetReferencedAssemblies().Select(Assembly.Load);
            foreach (var assembly in refAssemblies)
            {
                var candidates = assembly.GetExportedTypes().Where( x => 
                    x.IsClass && 
                    !x.IsAbstract  && 
                    x.BaseType.IsGenericType && 
                    x.BaseType.GetGenericTypeDefinition() == typeof(DataProvider<,>));

                foreach (var candidate in candidates)
                {
                    providerTypes.Add(candidate);
                }
            }

            services.
                AddMvc(c =>
                    c.Conventions.Add(
                        new GenericControllerRouteConvention()
                )).
                ConfigureApplicationPartManager(o => 
                {
                    var contollerFeature = new ControllerFeature();

                    foreach (var providerType in providerTypes)
                    {
                        contollerFeature.Controllers.Add(
                                typeof(DataProviderContoller<,,>)
                                .MakeGenericType(
                                    providerType, 
                                    providerType.BaseType.GetGenericArguments()[0], 
                                    providerType.BaseType.GetGenericArguments()[1])
                                .GetTypeInfo());
                    }  

                    o.PopulateFeature(contollerFeature);                                       
                });

通用控制器


 public class DataProviderContoller<TProvider, TModel, TKey> : Controller
        where TProvider : DataProvider<TModel, TKey> 
    {
        private readonly DataProvider<TModel, TKey> _dataProvider;

        public DataProviderContoller(TProvider dataProvider)
        {
            _dataProvider = dataProvider ?? throw new ArgumentNullException(nameof(dataProvider));
        }        

    }

1 个答案:

答案 0 :(得分:1)

已解决

直接在启动类中添加逻辑是导致我出现问题的原因。在应用程序启动生命周期的另一个时间点,控制器功能的填充功能将被覆盖。我必须创建一个从I应用程序功能提供者继承的类:

GenericControllerFeatureProvider : IApplicationFeatureProvider<ControllerFeature>

在启动类中注册

 services.AddMvc(c =>
                c.Conventions.Add(new GenericControllerRouteConvention()
            ))
            .ConfigureApplicationPartManager(apm =>
            {
                apm.FeatureProviders.Add(new GenericControllerFeatureProvider(GetDataProviders()));
            });