标题:从零开始实现ASP.NET Core MVC的插件式开发(九) - 升级.NET 5及启用预编译视图
作者:Lamond Lu
地址:https://www.cnblogs.com/lwqlun/p/13992077.html
源代码:https://github.com/lamondlu/Mystique
适用版本:.NET Core 3.1
,.NET 5
前景回顾
- 从零开始实现ASP.NET Core MVC的插件式开发(一) - 使用Application Part动态加载控制器和视图
- 从零开始实现ASP.NET Core MVC的插件式开发(二) - 如何创建项目模板
- 从零开始实现ASP.NET Core MVC的插件式开发(三) - 如何在运行时启用组件
- 从零开始实现ASP.NET Core MVC的插件式开发(四) - 插件安装
- 从零开始实现ASP.NET Core MVC的插件式开发(五) - 使用AssemblyLoadContext实现插件的升级和删除
- 从零开始实现ASP.NET Core MVC的插件式开发(六) - 如何加载插件引用
- 从零开始实现ASP.NET Core MVC的插件式开发(七) - 近期问题汇总及部分解决方案
- 从零开始实现ASP.NET Core MVC的插件式开发(八) - Razor视图相关问题及解决方案
简介
在这个项目创建的时候,项目的初衷是使用预编译视图来呈现界面,但是由于多次尝试失败,最后改用了运行时编译视图,这种方式在第一次加载的时候非常的慢,所有的插件视图都要在运行时编译,而且从便携性上来说,预编译视图更好。近日,在几位同道的共同努力下,终于实现了这种加载方式。
此篇要鸣谢网友 j4587698 和 yang-er 对针对当前项目的支持,你们的思路帮我解决了当前项目针对不能启用预编译视图的2个主要的问题
- 在当前项目目录结构下,启动时加载组件,组件预编译视图不能正常使用
- 运行时加载组件之后,组件中的预编译视图不能正常使用
升级.NET 5
随着.NET 5的发布,当前项目也升级到了.NET 5版本。
整个升级的过程比我预想的简单的多,只是修改了一下项目使用的Target fremework
。重新编译打包了一下插件程序,项目就可以正常运行了,整个过程中没有产生任何因为版本升级导致的编译问题。
预编译视图不能使用的问题
在升级了.NET 5之后,我重新尝试在启动时关闭了运行时编译,加载预编译视图View, 借此测试.NET 5对预编译视图的支持情况。
public static void MystiqueSetup(this IServiceCollection services, IConfiguration configuration)
{
...
IMvcBuilder mvcBuilder = services.AddMvc();
ServiceProvider provider = services.BuildServiceProvider();
using (IServiceScope scope = provider.CreateScope())
{
...
foreach (ViewModels.PluginListItemViewModel plugin in allEnabledPlugins)
{
CollectibleAssemblyLoadContext context = new CollectibleAssemblyLoadContext(plugin.Name);
string moduleName = plugin.Name;
string filePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Modules", moduleName, $"{moduleName}.dll");
string viewFilePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Modules", moduleName, $"{moduleName}.Views.dll");
string referenceFolderPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Modules", moduleName);
_presets.Add(filePath);
using (FileStream fs = new FileStream(filePath, FileMode.Open))
{
Assembly assembly = context.LoadFromStream(fs);
context.SetEntryPoint(assembly);
loader.LoadStreamsIntoContext(context, referenceFolderPath, assembly);
MystiqueAssemblyPart controllerAssemblyPart = new MystiqueAssemblyPart(assembly);
mvcBuilder.PartManager.ApplicationParts.Add(controllerAssemblyPart);
PluginsLoadContexts.Add(plugin.Name, context);
BuildNotificationProvider(assembly, scope);
}
using (FileStream fsView = new FileStream(viewFilePath, FileMode.Open))
{
Assembly viewAssembly = context.LoadFromStream(fsView);
loader.LoadStreamsIntoContext(context, referenceFolderPath, viewAssembly);
CompiledRazorAssemblyPart moduleView = new CompiledRazorAssemblyPart(viewAssembly);
mvcBuilder.PartManager.ApplicationParts.Add(moduleView);
}
context.Enable();
}
}
}
AssemblyLoadContex