更新时间:2023-02-12 13:13:36
根据您的评论和代码,您与实现这一目标的方式大致相同.请注意,我已经对示例进行了大量缩减,以便我可以设置一个测试.
Based on your comment and code you were pretty much on par with how you would achieve this. Note I have cut down the example quite a bit so I could setup a test.
假设我有一个基本的通用控制器:
Say I have a basic generic controller as:
public class GenericController<T> : Controller
where T: class
{
public IActionResult Get()
{
return Content(typeof(T).FullName);
}
}
我现在有一个带 Get 动作的类型化控制器.现在你的大部分代码都是正确的.所以我的功能提供者为(注意我有一个静态类型数组):
I now have a typed controller with Get action. Now most of your code was right on the money. So my Feature Provider as (note i have a static array of types):
public class GenericControllerFeatureProvider : IApplicationFeatureProvider<ControllerFeature>
{
public void PopulateFeature(IEnumerable<ApplicationPart> parts, ControllerFeature feature)
{
foreach (var entityConfig in ControllerEntity.EntityTypes)
{
var entityType = entityConfig;
var typeName = entityType.Name + "Controller";
if (!feature.Controllers.Any(t => t.Name == typeName))
{
var controllerType = typeof(GenericController<>)
.MakeGenericType(entityType)
.GetTypeInfo();
feature.Controllers.Add(controllerType);
}
}
}
}
接下来是 IControllerModelConvention
实现.
public class GenericControllerModelConvention : IControllerModelConvention
{
public void Apply(ControllerModel controller)
{
if (!controller.ControllerType.IsGenericType || controller.ControllerType.GetGenericTypeDefinition() != typeof(GenericController<>))
{
return;
}
var entityType = controller.ControllerType.GenericTypeArguments[0];
controller.ControllerName = entityType.Name + "Controller";
controller.RouteValues["Controller"] = entityType.Name;
}
}
最后,启动是所有魔法发生的地方.基本上我们将IControllerModelConvention
注册到MVC约定选项中,然后注册FeatureProvider
.
And finally the startup is where all the magic happens. Basically we register the IControllerModelConvention
into the MVC convention options, and then register the FeatureProvider
.
public void ConfigureServices(IServiceCollection services)
{
var mvcBuilder = services.AddMvc();
mvcBuilder.AddMvcOptions(o => o.Conventions.Add(new GenericControllerModelConvention()));
mvcBuilder.ConfigureApplicationPartManager(c =>
{
c.FeatureProviders.Add(new GenericControllerFeatureProvider());
});
}
根据我的评论,有两件事让我印象深刻.
From my review two things struck me.
GenericControllerNameConvention
作为属性?Controller
路由值隐式设置为您的实体类型(而不是类型 + 名称).GenericControllerNameConvention
as an attribute?Controller
Route Value to your entity type (not the type + name).给定两个实体(EntityA 和 EntityB),控制器的结果是
Given two entities (EntityA and EntityB) the result of the controllers is
/Entitya/get/
打印 WebApplication11.Infrastructure.EntityA
/Entityb/get/
打印 WebApplication11.Infrastructure.EntityB