ASP.Net运行时核心注册Controller
ASP.Net Core register Controller at runtime
我问自己是否可以在运行时加载一个包含 Controller
s 的 DLL 并使用它。
我找到的唯一解决方案是通过 ApplicationPart
在 StartUp
:
上添加程序集
var builder = services.AddMvc();
builder.AddApplicationPart(
AssemblyLoadContext.Default.LoadFromAssemblyPath(
@"PATH\ExternalControllers.dll"
));
有谁知道是否可以随时注册 Controller
,因为该解决方案的问题是,当您想要添加另一个 DLL 时,您必须重新启动 WebService
Controller
s 在里面。如果您可以随时添加它们并随时在应用程序中注册它们,那就太好了。
现在这是可能的。
请参阅有关 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);
}
}
}
}
现在可以在 .net core 2.0+
请看代码ActionDescriptorCollectionProvider.cs:
public ActionDescriptorCollectionProvider(
IEnumerable<IActionDescriptorProvider> actionDescriptorProviders,
IEnumerable<IActionDescriptorChangeProvider> actionDescriptorChangeProviders)
{
_actionDescriptorProviders = actionDescriptorProviders
.OrderBy(p => p.Order)
.ToArray();
_actionDescriptorChangeProviders = actionDescriptorChangeProviders.ToArray();
ChangeToken.OnChange(
GetCompositeChangeToken,
UpdateCollection);
}
步骤1:ImplementIActionDescriptorChangeProviderclass:
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);
}
}
2:AddSingleton Startup.ConfigureServices() 步:
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc();
services.AddSingleton<IActionDescriptorChangeProvider>(MyActionDescriptorChangeProvider.Instance);
services.AddSingleton(MyActionDescriptorChangeProvider.Instance);
}
第 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");
}
}
我问自己是否可以在运行时加载一个包含 Controller
s 的 DLL 并使用它。
我找到的唯一解决方案是通过 ApplicationPart
在 StartUp
:
var builder = services.AddMvc();
builder.AddApplicationPart(
AssemblyLoadContext.Default.LoadFromAssemblyPath(
@"PATH\ExternalControllers.dll"
));
有谁知道是否可以随时注册 Controller
,因为该解决方案的问题是,当您想要添加另一个 DLL 时,您必须重新启动 WebService
Controller
s 在里面。如果您可以随时添加它们并随时在应用程序中注册它们,那就太好了。
现在这是可能的。
请参阅有关 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);
}
}
}
}
现在可以在 .net core 2.0+
请看代码ActionDescriptorCollectionProvider.cs:
public ActionDescriptorCollectionProvider(
IEnumerable<IActionDescriptorProvider> actionDescriptorProviders,
IEnumerable<IActionDescriptorChangeProvider> actionDescriptorChangeProviders)
{
_actionDescriptorProviders = actionDescriptorProviders
.OrderBy(p => p.Order)
.ToArray();
_actionDescriptorChangeProviders = actionDescriptorChangeProviders.ToArray();
ChangeToken.OnChange(
GetCompositeChangeToken,
UpdateCollection);
}
步骤1:ImplementIActionDescriptorChangeProviderclass:
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);
}
}
2:AddSingleton Startup.ConfigureServices() 步:
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc();
services.AddSingleton<IActionDescriptorChangeProvider>(MyActionDescriptorChangeProvider.Instance);
services.AddSingleton(MyActionDescriptorChangeProvider.Instance);
}
第 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");
}
}