经过一段时间的工作后ControllerFeature
直接没有结果,是时候回到基础了。
基本上在应用程序启动时注册控制器into控制器功能容器not from控制器功能。这是关键,因为您需要注册控制器。
我正在浏览RC2 的 GitHub 存储库并遇到了ControllerFeatureProvider。就像声明的那样。
Discovers controllers from a list of <see cref="ApplicationPart"/>
然后还有一个方法进一步深入PopulateFeature
我们可以看到它抓取了注册到应用程序的所有部分并提取了控制器接口(IsController()
方法值得回顾)。
/// <inheritdoc />
public void PopulateFeature(
IEnumerable<ApplicationPart> parts,
ControllerFeature feature)
{
foreach (var part in parts.OfType<IApplicationPartTypeProvider>())
{
foreach (var type in part.Types)
{
if (IsController(type) && !feature.Controllers.Contains(type))
{
feature.Controllers.Add(type);
}
}
}
}
现在我们知道控制器是如何找到的,它们来自ApplicationPart注册到应用程序。下一个问题是我们如何创建应用程序部分.
经过一番审查并尝试使用依赖项注入,手动将部件添加到应用程序以注册我的部件后,我遇到了另一个概念。
界面IMvcBuilder有扩展方法AddApplicationPart这增加了一个Assembly
到应用部分。这是通过将组件包装在一个AssemblyPart应用部分。经审查AssemblyPart
该部分将程序集中找到的所有类型返回到调用部分系统(在我们的例子中ControllerFeatureProvider
).
/// <inheritdoc />
public IEnumerable<TypeInfo> Types => Assembly.DefinedTypes;
现在有一些有趣的事情AssemblyPart
是方法GetReferencePaths()
/// <inheritdoc />
public IEnumerable<string> GetReferencePaths()
{
var dependencyContext = DependencyContext.Load(Assembly);
if (dependencyContext != null)
{
return dependencyContext.CompileLibraries.SelectMany(library => library.ResolveReferencePaths());
}
// If an application has been compiled without preserveCompilationContext, return the path to the assembly
// as a reference. For runtime compilation, this will allow the compilation to succeed as long as it least
// one application part has been compiled with preserveCompilationContext and contains a super set of types
// required for the compilation to succeed.
return new[] { Assembly.Location };
}
看来最后的难题是启用preserveCompilationContext
在模块(或外部程序集)的project.json 文件中。
"preserveCompilationContext": {
"type": "boolean",
"description": "Set this option to preserve reference assemblies and other context data to allow for runtime compilation.",
"default": false
}
最后,这个问题的实现和解决变得非常简单。我们的每个外部程序集(或模块)都是通过我们的ModuleManager
班级。其中包含所有引用的模块程序集的列表。所以在ConfigureServices
方法中的Startup.cs
注册 MVC 的文件,我们只需调用扩展方法AddApplicationPart
对于每个模块组件。
var mvcBuilder = services.AddMvc();
foreach(var module in ModulesManager.ReferencedModules)
{
mvcBuilder.AddApplicationPart(module.ReferencedAssembly);
}
一旦做出这些小改变,我的外部控制器就停止返回404
.