I am asking myself if it is possible to load a DLL with Controller
s in it at runtime and use it.
The only solution I've found is to add an assembly via ApplicationPart
on the StartUp
:
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. 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+
Please see code 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:
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():
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc();
services.AddSingleton<IActionDescriptorChangeProvider>(MyActionDescriptorChangeProvider.Instance);
services.AddSingleton(MyActionDescriptorChangeProvider.Instance);
}
Step 3: Register controller at runtime:
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");
}
}