从零开始实现ASP.NET Core MVC的插件式开发(八) - Razor视图相关问题及解决方案

标题:从零开始实现ASP.NET Core MVC的插件式开发(八) - Razor视图相关问题及解决方案
作者:Lamond Lu
地址:https://www.cnblogs.com/lwqlun/p/13197683.html
源代码:https://github.com/lamondlu/Mystique

前景回顾

简介

在上一篇中,我给大家分享了程序调试问题的解决方案以及如何实现插件中的消息传递,完稿之后,又收到了不少问题反馈,其中最严重的问题应该就是运行时编译Razor视图失败的问题。

本篇我就给大家分享一下我针对此问题的解决方案,最后还会补上上一篇中鸽掉的动态加载菜单(T.T)。

Razor视图中引用出错问题

为了模拟一下当前的问题,我们首先之前的插件1中添加一个新类TestClass, 并在HelloWorld方法中创建一个TestClass对象作为视图模型传递给Razor视图,并在Razor视图中展示出TestClassMessage属性。

  • TestClass.cs
public class TestClass
{
    public string Message { get; set; }
}
  • HelloWorld.cshtml
@using DemoPlugin1.Models;
@model TestClass
@{

}

<h1>@ViewBag.Content</h1>
<h2>@Model.Message</h2>

  • Plugin1Controller.cs
    [Area("DemoPlugin1")]
    public class Plugin1Controller : Controller
    {
        private INotificationRegister _notificationRegister;

        public Plugin1Controller(INotificationRegister notificationRegister)
        {
            _notificationRegister = notificationRegister;
        }

        [HttpGet]
        public IActionResult HelloWorld()
        {
            string content = new Demo().SayHello();
            ViewBag.Content = content + "; Plugin2 triggered";

            TestClass testClass = new TestClass();
            testClass.Message = "Hello World";

            _notificationRegister.Publish("LoadHelloWorldEvent", JsonConvert.SerializeObject(new LoadHelloWorldEvent() { Str = "Hello World" }));

            return View(testClass);
        }
    }

这个代码看似很简单,也是最常用的MVC视图展示方式,但是集成在动态组件系统中之后,你就会得到以下错误界面。

这里看起来似乎依然感觉是AssemblyLoadContext的问题。主要的线索是,如果你将插件1的程序集直接引入主程序工程中,重新启动项目之后,此处代码能够正常访问,所以我猜想Razor视图才进行运行时编译的时候,使用了默认的AssemblyLoadContext,而非插件AssemblyPart所在的AssemblyLoadContext

由此我做了一个实验,我在MystiqueSetup方法中,在插件加载的时候,也向默认AssemblyLoadContext中加载了插件程序集

    public static void MystiqueSetup(this IServiceCollection services, 
		IConfiguration configuration)
    {

        ...
        using (IServiceScope scope = provider.CreateScope())
        {
            MvcRazorRuntimeCompilationOptions option = scope.ServiceProvider.GetService<MvcRazorRuntimeCompilationOptions>();

            IUnitOfWork unitOfWork = scope.ServiceProvider.GetService<IUnitOfWork>();
            List<ViewModels.PluginListItemViewModel> allEnabledPlugins = unitOfWork.PluginRepository.GetAllEnabledPlugins();
            IReferenceLoader loader = scope.ServiceProvider.GetService<IReferenceLoader>();

            foreach (ViewModels.PluginListItemViewModel plugin in allEnabledPlugins)
            {
                ...
                using (FileStream fs = new FileStream(filePath, FileMode.Open))
                {
                    System.Reflection.Assembly assembly = context.LoadFromStream(fs);
                    context.SetEntryPoint(assembly);
                    loader.LoadStreamsIntoContext(context, referenceFolderPath, assembly);

                    ...

                    fs.Position = 0;
                    AssemblyLoadContext.Default.LoadFromStream(fs);
                }

                context.Enable();
            }
        }

        ...

    }

重新运行程序,访问插件1的路由,你就会得到以下错误。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值