加入收藏 | 设为首页 | 会员中心 | 我要投稿 东莞站长网 (https://www.0769zz.com/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 站长学院 > Asp教程 > 正文

ASP.NET Core MVC如何实现运行时动态定义Controller类型

发布时间:2020-06-18 11:26:36 所属栏目:Asp教程 来源:站长网
导读:副标题#e# 昨天有个朋友在微信上问我一个问题:他希望通过动态脚本的形式实现对ASP.NET Core MVC应用的扩展,比如在程序运行过程中上传一段C#脚本将其中定义的Controller类型注册到应用中,问我是否有好解决方案。我当时在外边,回复不太方便,所以只给他说

DynamicActionProvider 解决了将提供的源代码向对应ActionDescriptor列表的转换,但是MVC默认情况下对提供的ActionDescriptor对象进行了缓存。如果框架能够使用新的ActionDescriptor对象,需要告诉它当前应用提供的ActionDescriptor列表发生了改变,而这可以利用自定义的IActionDescriptorChangeProvider来实现。为此我们定义了如下这个DynamicChangeTokenProvider类型,该类型实现了IActionDescriptorChangeProvider接口,并利用GetChangeToken方法返回IChangeToken对象通知MVC框架当前的ActionDescriptor已经发生改变。从实现实现代码可以看出,当我们调用NotifyChanges方法的时候,状态改变通知会被发出去。

public class DynamicChangeTokenProvider : IActionDescriptorChangeProvider { private CancellationTokenSource _source; private CancellationChangeToken _token; public DynamicChangeTokenProvider() { _source = new CancellationTokenSource(); _token = new CancellationChangeToken(_source.Token); } public IChangeToken GetChangeToken() => _token; public void NotifyChanges() { var old = Interlocked.Exchange(ref _source, new CancellationTokenSource()); _token = new CancellationChangeToken(_source.Token); old.Cancel(); } }

五、应用构建

到目前为止,核心的两个类型DynamicActionProvider和DynamicChangeTokenProvider已经定义好了,接下来我们按照如下的方式将它们注册到MVC应用的依赖注入框架中。

public class Program { public static void Main() { Host.CreateDefaultBuilder() .ConfigureWebHostDefaults(web => web .ConfigureServices(svcs => svcs .AddSingleton<ICompiler, Compiler>() .AddSingleton<DynamicActionProvider>() .AddSingleton<DynamicChangeTokenProvider>() .AddSingleton<IActionDescriptorProvider>(provider => provider.GetRequiredService<DynamicActionProvider>()) .AddSingleton<IActionDescriptorChangeProvider>(provider => provider.GetRequiredService<DynamicChangeTokenProvider>()) .AddRouting().AddControllersWithViews()) .Configure(app => app .UseRouting() .UseEndpoints(endpoints => endpoints.MapControllerRoute( name: default, pattern: "{controller}/{action}" )))) .Build() .Run(); } }

然后我们定义了如下这个HomeController。针对GET请求的Index方法会将上图所示的视图呈现出来。当我们点击“Register”按钮之后,提交的源代码会通过针对POST请求的Index方法进行处理。如下面的代码片段所示,在将将提交的源代码作为参数调用了DynamicActionProvider对象的 AddControllers方法之后,我们调用了DynamicChangeTokenProvider对象的 NotifyChanges方法。

public class HomeController : Controller { [HttpGet("http://www.jb51.net/")] public IActionResult Index() => View(); [HttpPost("http://www.jb51.net/")] public IActionResult Index( string source, [FromServices]DynamicActionProvider actionProvider, [FromServices] DynamicChangeTokenProvider tokenProvider) { try { actionProvider.AddControllers(source); tokenProvider.NotifyChanges(); return Content("OK"); } catch (Exception ex) { return Content(ex.Message); } } }

如下所示的是View的定义。

(编辑:东莞站长网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

热点阅读