简体   繁体   English

ASP.Net Core 在运行时注册控制器

[英]ASP.Net Core register Controller at runtime

I am asking myself if it is possible to load a DLL with Controller s in it at runtime and use it.我问自己是否可以在运行时加载一个包含Controller的 DLL 并使用它。

The only solution I've found is to add an assembly via ApplicationPart on the StartUp :我发现的唯一解决方案是通过ApplicationPartStartUp上添加程序集:

var builder = services.AddMvc();
builder.AddApplicationPart(
    AssemblyLoadContext.Default.LoadFromAssemblyPath(
        @"PATH\ExternalControllers.dll"
));

Do anyone know if it is possible to register Controller at any time, because the issue with that solution is, that you have to restart the WebService when you want to add another DLL with Controller s in it.有谁知道是否可以随时注册Controller ,因为该解决方案的问题是,当您想添加另一个包含Controller的 DLL 时,您必须重新启动WebService It would be nice when you just can add them at any time and register them at any time in the application.如果您可以随时添加它们并在应用程序中随时注册它们,那就太好了。

This is possible now on .net core 2.0+这现在在 .net core 2.0+ 上是可能的

Please see code ActionDescriptorCollectionProvider.cs :请参阅代码ActionDescriptorCollectionProvider.cs

    public ActionDescriptorCollectionProvider(
        IEnumerable<IActionDescriptorProvider> actionDescriptorProviders,
        IEnumerable<IActionDescriptorChangeProvider> actionDescriptorChangeProviders)
    {
        _actionDescriptorProviders = actionDescriptorProviders
            .OrderBy(p => p.Order)
            .ToArray();

        _actionDescriptorChangeProviders = actionDescriptorChangeProviders.ToArray();

        ChangeToken.OnChange(
            GetCompositeChangeToken,
            UpdateCollection);
    }

Step 1:Implement IActionDescriptorChangeProvider class:第一步:实现IActionDescriptorChangeProvider类:

public class MyActionDescriptorChangeProvider : IActionDescriptorChangeProvider
{
    public static MyActionDescriptorChangeProvider Instance { get; } = new MyActionDescriptorChangeProvider();

    public CancellationTokenSource TokenSource { get; private set; }

    public bool HasChanged { get; set; }

    public IChangeToken GetChangeToken()
    {
        TokenSource = new CancellationTokenSource();
        return new CancellationChangeToken(TokenSource.Token);
    }
}

Step 2:AddSingleton on Startup.ConfigureServices():第 2 步:在 Startup.ConfigureServices() 上添加单例:

public void ConfigureServices(IServiceCollection services)
{
    services.AddMvc();
    services.AddSingleton<IActionDescriptorChangeProvider>(MyActionDescriptorChangeProvider.Instance);
    services.AddSingleton(MyActionDescriptorChangeProvider.Instance);
}

Step 3: Register controller at runtime:第 3 步:在运行时注册控制器:

public class TestController : Controller
{
    private readonly ApplicationPartManager _partManager;
    private readonly IHostingEnvironment _hostingEnvironment;
    public TestController(
        ApplicationPartManager partManager,
        IHostingEnvironment env)
    {
        _partManager = partManager;
        _hostingEnvironment = env;
    }
    public IActionResult RegisterControllerAtRuntime()
    {
        string assemblyPath = @"PATH\ExternalControllers.dll";
        var assembly = AssemblyLoadContext.Default.LoadFromAssemblyPath(assemblyPath);
        if (assembly != null)
        {
            _partManager.ApplicationParts.Add(new AssemblyPart(assembly));
            // Notify change
            MyActionDescriptorChangeProvider.Instance.HasChanged = true;
            MyActionDescriptorChangeProvider.Instance.TokenSource.Cancel();
            return Content("1");
        }
        return Content("0");
    }
}

This is possible now.现在这是可能的。

Please see the updated documentation about how to add dynamic controllers :请参阅有关如何添加动态控制器的更新文档:

public class GenericControllerFeatureProvider : IApplicationFeatureProvider<ControllerFeature>
{
    public void PopulateFeature(IEnumerable<ApplicationPart> parts, ControllerFeature feature)
    {
        // This is designed to run after the default ControllerTypeProvider, 
        // so the list of 'real' controllers has already been populated.
        foreach (var entityType in EntityTypes.Types)
        {
            var typeName = entityType.Name + "Controller";
            if (!feature.Controllers.Any(t => t.Name == typeName))
            {
                // There's no 'real' controller for this entity, so add the generic version.
                var controllerType = typeof(GenericController<>)
                    .MakeGenericType(entityType.AsType()).GetTypeInfo();
                feature.Controllers.Add(controllerType);
            }
        }
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM