标题:从零开始实现ASP.NET Core MVC的插件式开发(六) - 如何加载插件引用。
作者:Lamond Lu
地址:https://www.cnblogs.com/lwqlun/p/11717254.html
源代码:https://github.com/lamondlu/DynamicPlugins
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-IeRz6YqP-1571701254481)(https://img2018.cnblogs.com/blog/65831/201910/65831-20191021235506621-170598947.jpg)]
前景回顾
- 从零开始实现ASP.NET Core MVC的插件式开发(一) - 使用Application Part动态加载控制器和视图
- 从零开始实现ASP.NET Core MVC的插件式开发(二) - 如何创建项目模板
- 从零开始实现ASP.NET Core MVC的插件式开发(三) - 如何在运行时启用组件
- 从零开始实现ASP.NET Core MVC的插件式开发(四) - 插件安装
- 从零开始实现ASP.NET Core MVC的插件式开发(五) - 使用AssemblyLoadContext实现插件的升级和删除
简介
在前一篇中,我给大家演示了如何使用.NET Core 3.0中新引入的AssemblyLoadContext
来实现运行时升级和删除插件。完成此篇之后,我得到了很多园友的反馈,很高兴有这么多人能够参与进来,我会根据大家的反馈,来完善这个项目。本篇呢,我将主要解决加载插件引用的问题,这个也是反馈中被问的最多的问题。
问题用例
在之前做的插件中,我们做的都是非常非常简单的功能,没有引入任何的第三方库。但是正常情况下,我们所创建的插件或多或少的都会引用一些第三方库,那么下面我们来尝试一下,使用我们先前的项目,加载一个使用第三方程序集, 看看会的得到什么结果。
这里为了模拟,我创建了一个新的类库项目DemoReferenceLibrary
, 并在之前的DemoPlugin1
项目中引用DemoReferenceLibrary
项目。
在DemoReferenceLibrary
中,我新建了一个类Demo.cs文件, 其代码如下:
public class Demo
{
public string SayHello()
{
return "Hello World. Version 1";
}
}
这里就是简单的通过SayHello
方法,返回了一个字符串。
然后在DemoPlugin1
项目中,我们修改之前创建的Plugin1Controller
,从Demo
类中通过SayHello
方法得到需要在页面中显示的字符串。
[Area("DemoPlugin1")]
public class Plugin1Controller : Controller
{
public IActionResult HelloWorld()
{
var content = new Demo().SayHello();
ViewBag.Content = content;
return View();
}
}
最后我们打包一下插件,重新将其安装到系统中,访问插件路由之后,就会得到以下错误。
这里就是大部分同学遇到的问题,无法加载程序集DemoReferenceLibrary
。
如何加载插件引用?
这个问题的原因很简单,就是当通过AssemblyLoadContext
加载程序集的时候,我们只加载了插件程序集,没有加载它引用的程序集。
例如,我们以DemoPlugin1
的为例,在这个插件的目录如下
在这个目录中,除了我们熟知的DemoPlugin1.dll
,DemoPlugin1.Views.dll
之外,还有一个DemoReferenceLibrary.dll
文件。 这个文件我们并没有在插件启用时加载到当前的AssemblyLoadContext
中,所以在访问插件路由时,系统找不到这个组件的dll文件。
为什么Mystique.Core.dll
、System.Data.SqlClient.dll
、Newtonsoft.Json.dll
这些DLL不会出现问题呢?
在.NET Core中有2种LoadContext
。 一种是我们之前介绍的AssemblyLoadContext
, 它是一种自定义LoadContext
。 另外一种就是系统默认的DefaultLoadContext
。当一个.NET Core应用启动的时候,都会创建并引用一个DefaultLoadContext
。
如果没有指定LoadContext
, 系统默认会将程序集都加载到DefaultLoadContext
中。这里我们可以查看一下我们的主站点项目,这个项目我们也引用了Myst