C# 另一个部件中的MVC 6 RC2控制器

C# 另一个部件中的MVC 6 RC2控制器,c#,asp.net-core-mvc,C#,Asp.net Core Mvc,在MVC 6 RC1中,我们使用IAssemlbyProvider接口注册在运行时发现的程序集,并以类似的方式注入其他控制器类型。。现在,随着RC2的发布,IAssemblyProvider已被删除并更改为 我们的框架版本目前是net46 由于升级,外部组件(未引用)中的控制器将返回404状态 我们已尝试通过ApplicationPartManager将控制器手动添加到注册的控制器 var mvcBuilder = services.AddMvc(); var controllerFeature

在MVC 6 RC1中,我们使用
IAssemlbyProvider
接口注册在运行时发现的程序集,并以类似的方式注入其他控制器类型。。现在,随着RC2的发布,
IAssemblyProvider
已被删除并更改为

我们的框架版本目前是
net46

由于升级,外部组件(未引用)中的控制器将返回
404
状态

我们已尝试通过
ApplicationPartManager
将控制器手动添加到注册的控制器

var mvcBuilder = services.AddMvc();
var controllerFeature = new ControllerFeature();
mvcBuilder.PartManager.PopulateFeature(controllerFeature);

var moduleControllers = ModulesManager.GetControllers();
foreach (var c in moduleControllers)
    controllerFeature.Controllers.Add(c);

mvcBuilder.PartManager.PopulateFeature(controllerFeature);
而且

services.AddMvc().ConfigureApplicationPartManager(app =>
{
    var controllerFeature = new ControllerFeature();
    app.PopulateFeature(controllerFeature);

    var moduleControllers = ModulesManager.GetControllers();
    foreach (var c in moduleControllers)
        controllerFeature.Controllers.Add(c);

    app.PopulateFeature(controllerFeature);
});
现在,程序集肯定已加载到
AppDomain
,因为我们的依赖项注入系统正在为外部程序集中的其他项查找和填充服务

在我们以前的实现中,使用
IAssemblyProvider
可以很好地实现这一点

public class ModuleAwareAssemblyProvider : IAssemblyProvider
{
    private readonly DefaultAssemblyProvider _defaultProvider;

    public ModuleAwareAssemblyProvider(DefaultAssemblyProvider defaultProvider)
    {
        _defaultProvider = defaultProvider;
    }

    public IEnumerable<Assembly> CandidateAssemblies
    {
        get
        {
            return _defaultProvider.CandidateAssemblies.Concat(ModulesManager.Assemblies).Distinct();
        }
    }
}
/// <inheritdoc />
public IEnumerable<TypeInfo> Types => Assembly.DefinedTypes;
公共类模块WAREASEMBLYPROVIDER:IASEMBLYPROVIDER
{
私有只读DefaultAssemblyProvider\u defaultProvider;
公共模块WareAssemblyProvider(DefaultAssemblyProvider defaultProvider)
{
_defaultProvider=defaultProvider;
}
公共IEnumberable候选程序集
{
得到
{
返回_defaultProvider.CandidateAssemblies.Concat(modulemanager.Assemblies).Distinct();
}
}
}
我知道RC2还是相对较新的,但如果有人有在启动时注册额外控制器的经验,那将很有帮助


干杯,Nico

在花了一段时间直接使用
控制器功能
之后,没有任何结果,现在是时候回到基础了

基本上,在应用程序启动时,控制器注册到控制器功能容器中,而不是从控制器功能中注册。这是关键,因为您需要注册控制器

我正在浏览网页,无意中看到了。如前所述

现在我们知道了控制器是如何找到的,它们来自注册到应用程序的。下一个问题是如何创建应用程序部件

经过一些审查并尝试使用依赖注入,手动将部件添加到应用程序以注册部件,我遇到了另一个概念

该接口具有扩展方法,可向应用程序部件添加
程序集
。这是通过将程序集包装到应用程序零件中来完成的。查看
AssemblyPart
时,此部件将在部件中找到的所有类型返回给调用部件系统(在本例中为
ControllerFeatureProvider

最后一个难题似乎是在模块(或外部程序集的)project.json文件中启用
preserveComilationContext

"preserveCompilationContext": {
    "type": "boolean",
    "description": "Set this option to preserve reference assemblies and other context data to allow for runtime compilation.",
    "default": false
}
最后,实现和解决这个问题变得非常简单。我们的每个外部程序集(或模块)都是通过
ModuleManager
类加载的。这包含所有引用模块程序集的列表。因此,在注册MVC的
Startup.cs
文件中的
ConfigureServices
方法中,我们只需将每个模块组件的扩展方法
AddApplicationPart
称为

var mvcBuilder = services.AddMvc();
foreach(var module in ModulesManager.ReferencedModules)
{
    mvcBuilder.AddApplicationPart(module.ReferencedAssembly);
}

在进行这些小更改后,我的外部控制器停止返回
404

只需添加启动->配置服务

services.AddMvc()
.AddApplicationPart(typeof(OtherAssemblyController).GetTypeInfo().Assembly)
.AddControllersAsServices();

我使用应用程序部分使用以下生成器扩展方法来实现插件功能。我希望它对某人有用

ASP.NET核心1.1 召唤


我对你的
ModuleManager
类有点困惑。是
ModuleManager
还是
ModuleManager
?不管怎样,我似乎在任何文档或源代码中都找不到对它的引用。如何获取它并逐步浏览
ReferencedModules
?模块管理器是一个自定义类(我们自己的类),用于根据特定路径和引用版本查找模块。你应该能够轻松地实现你自己的版本,因为你认为合适。谢谢你的解释<代码>保留编译上下文帮了我的忙。我无法相信整个asp.net核心的文档记录是多么糟糕。我了解其新的但更高级的文档将非常受欢迎。感谢您的研究,这正是我需要了解的类似情况。OtherAssemblyController位于从属项目中,我无法添加对它的引用。那我该怎么办?
"preserveCompilationContext": {
    "type": "boolean",
    "description": "Set this option to preserve reference assemblies and other context data to allow for runtime compilation.",
    "default": false
}
var mvcBuilder = services.AddMvc();
foreach(var module in ModulesManager.ReferencedModules)
{
    mvcBuilder.AddApplicationPart(module.ReferencedAssembly);
}
services.AddMvc()
.AddApplicationPart(typeof(OtherAssemblyController).GetTypeInfo().Assembly)
.AddControllersAsServices();
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using System.IO;
using System.Runtime.Loader;

namespace AppPartTest1.Web.Helpers.Features
{
    public static class FeaturesBuilderExtensions
    {
        //
        // Summary:
        //     Adds Features supports to the Application.
        //
        // Parameters:
        //   builder:
        //     The Microsoft.Extensions.DependencyInjection.IMvcBuilder.
        public static IMvcBuilder AddFeaturesSupport(this IMvcBuilder builder, IConfigurationRoot Configuration, IHostingEnvironment environment)
        {

            var fileNames = Directory.GetFiles("Features", "*.dll");

            foreach (string fileName in fileNames)
            {
                builder.AddApplicationPart(AssemblyLoadContext.Default.LoadFromAssemblyPath(Path.Combine(environment.ContentRootPath, fileName)));
            }

            return builder;
        }
    }
}
    public Startup(IHostingEnvironment env)
    {
        var builder = new ConfigurationBuilder()
            .SetBasePath(env.ContentRootPath)
            .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
            .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true)
            .AddEnvironmentVariables();
        Configuration = builder.Build();

        environment = env;
    }

    public IHostingEnvironment environment { get; set; }
    public IConfigurationRoot Configuration { get; }

    // This method gets called by the runtime. Use this method to add services to the container.
    public void ConfigureServices(IServiceCollection services)
    {
        // Add framework services.
        var builder = services.AddMvc()
            .AddFeaturesSupport(this.Configuration, this.environment);
    }