.NET 6 AssemblyLoadContext DLL 库 热插拔逻辑实现

曾经也实现过.Net Framework 基于AppDomain 的 dll库热插拔,经历了版本的迭代,.Net Core 不支持 AppDomain,之前也搞过.Net Core 3.1 版本的,现在搞一下子.NET 6.0的。

热插拔运用的场景

主要运用到宿主与插件这个场景或者动态任务的场景上(假设你现在业务服务已经运行,但是,需要新增加新的业务功能,就可以用这种方式)。

就像Office 或者 Visual Studio 一样,它们都是集插件架构之大成者。

逻辑实现

主要是根据 AssemblyLoadContext 这个系统提供的API来实现的,已经实现了对DLL程序集的加载和卸载。

之前AppDomain是通过程序域(隔离的环境)的概念进行隔离的,而 AssemblyLoadContext 的话,提供了程序集加载隔离,它允许在单个进程中加载同一程序集的多个版本。

它替换.NET Framework中多个AppDomain实例提供的隔离机制,其中AssemblyLoadContext.Default 表示运行时的默认上下文,该上下文用于应用程序主程序集及其静态依赖项,那么,其他的上下文,就是插件DLL的上下文了。

从概念上讲,加载上下文会创建一个用于加载、解析和可能卸载一组程序集的范围。

这里就根据 AssemblyLoadContext 加载,卸载,来实现热插播逻辑的实现.

实现逻辑

主要的逻辑是这个逻辑

/// <summary>/// dll文件的加载/// </summary>public class LoadDll{/// <summary>/// 任务实体/// </summary>public ITask _task;public Thread _thread;/// <summary>/// 核心程序集加载/// </summary>public AssemblyLoadContext _AssemblyLoadContext { get; set; }/// <summary>/// 获取程序集/// </summary>public Assembly _Assembly { get; set; }/// <summary>/// 文件地址/// </summary>public string filepath = string.Empty;/// <summary>/// 指定位置的插件库集合/// </summary>AssemblyDependencyResolver resolver { get; set; }public bool LoadFile(string filepath){this.filepath = filepath;try{resolver = new AssemblyDependencyResolver(filepath);_AssemblyLoadContext = new AssemblyLoadContext(Guid.NewGuid().ToString("N"), true);_AssemblyLoadContext.Resolving += _AssemblyLoadContext_Resolving;using (var fs = new FileStream(filepath, FileMode.Open, FileAccess.Read)){var _Assembly = _AssemblyLoadContext.LoadFromStream(fs);var Modules = _Assembly.Modules;foreach (var item in _Assembly.GetTypes()){if (item.GetInterface("ITask") != null){_task = (ITask)Activator.CreateInstance(item);break;}}return true;}}catch (Exception ex) { Console.WriteLine($"LoadFile:{ex.Message}"); };return false;}private Assembly _AssemblyLoadContext_Resolving(AssemblyLoadContext arg1, AssemblyName arg2){Console.WriteLine($"加载{arg2.Name}");var path = resolver.ResolveAssemblyToPath(arg2);if (!string.IsNullOrEmpty(path)){using (var fs = new FileStream(path, FileMode.Open, FileAccess.Read)){return _AssemblyLoadContext.LoadFromStream(fs);}}return null;}public bool StartTask(){bool RunState = false;try{if (_task != null){_thread = new Thread(new ThreadStart(_Run));_thread.IsBackground = true;_thread.Start();RunState = true;}}catch (Exception ex) { Console.WriteLine($"StartTask:{ex.Message}"); };return RunState;}private void _Run(){try{_task.Run();}catch (Exception ex) { Console.WriteLine($"_Run 任务中断执行:{ex.Message}"); };}public bool UnLoad(){try{_thread?.Interrupt();}catch (Exception ex){ Console.WriteLine($"UnLoad:{ex.Message}");}finally{_thread = null;}_task = null;try{_AssemblyLoadContext?.Unload();}catch (Exception){ }finally{_AssemblyLoadContext = null;GC.Collect();GC.WaitForPendingFinalizers();}return true;}}

以上就是这个热插拔的核心逻辑了。

ITask.cs

这个接口实现简单,只有一个方法,当然,如果有需要,可以扩展一下。

/// <summary>/// 任务接口/// </summary>public interface ITask{/// <summary>/// 任务的运行方法/// </summary>/// <returns></returns>void Run();}

插件库1 PrintStrLib

插件的代码就很简单了

public class PrintStr : ITask{public void Run(){int a = 0;while (true){Console.WriteLine($"PrintStr:{a}");a++;Thread.Sleep(1 * 1000);}}}

插件库2 PrintDateLib

插件的代码就很简单了

public class PrintDate : ITask{public void Run(){while (true){Console.WriteLine($"PrintDate:{DateTime.Now}");Thread.Sleep(1 * 1000);}}}

测试运行

使用也很简单,加载程序集,然后,执行,间隔指定时间后,顺序卸载。

static void Main(string[] args)
{Console.Title = "AssemblyLoadContext Dll热插拔 测试 by 蓝总创精英团队";var list = new List<LoadDll>();Console.WriteLine("开始加载DLL");list.Add(Load(Path.Combine(AppDomain.CurrentDomain.BaseDirectory,"DLL", "PrintDateLib.dll")));list.Add(Load(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "DLL", "PrintStrLib.dll")));foreach (var item in list){item.StartTask();}Console.WriteLine("开启了任务!");SpinWait.SpinUntil(() => false, 5 * 1000);foreach (var item in list){var s = item.UnLoad();SpinWait.SpinUntil(() => false, 2 * 1000);Console.WriteLine($"任务卸载:{s}");}Console.WriteLine("热插拔插件任务 测试完毕");Console.ReadLine();
}
public static LoadDll Load(string filePath)
{var load = new LoadDll();load.LoadFile(filePath);return load;
}

效果查看

从下图来看,我们想要的结果都有了,加载两个插件,插件执行自己的业务,然后,顺序一个一个的卸载掉,确实已经不在执行它自己的业务了。

bcac5a1653218277b5d8dd7c53024f5b.png

总结

实际上.Net的程序集的隔离问题很多,这种隔离方式实际用的过程中,如果程序集简单还好,复杂的话,可能会有别的问题。

我非常喜欢的隔离方式就像谷歌游览器那样的插件方式或者IIS那样的容器级隔离,不过,这种实际上我分析是进程级隔离方案,现在也流行docker,系统级隔离。

只能说存在即合理吧,有它存在的价值。

代码地址

https://github.com/kesshei/AssemblyLoadContextDemo.git

https://gitee.com/kesshei/AssemblyLoadContextDemo.git

参考文档

https://docs.microsoft.com/zh-cn/dotnet/api/system.runtime.loader.assemblyloadcontext?view=net-6.0

一键三连呦!,感谢大佬的支持,您的支持就是我的动力!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/284938.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

C语言试题193之实现strcmp函数功能

📃个人主页:个人主页 🔥系列专栏:C语言试题200例 💬推荐一款刷算法、笔试、面经、拿大公司offer神器👉 点击跳转进入网站 ✅作者简介:大家好,我是码莎拉蒂,CSDN博客专家(全站排名Top 50),阿里云博客专家、51CTO博客专家、华为云享专家 1、题目 题目: 实现st…

[转]Webpack5(从入门到精通)

这里写目录标题 1、webpack 初体验 全局安装webpack2.打包样式资源 创建webpack.config.js文件&#xff08;配置文件&#xff09;3.打包html资源 webpack.config.js文件&#xff08;配置文件&#xff09;4.打包图片资源 webpack.config.js文件&#xff08;配置文件&#xff09;…

mybatis由浅入深day01_5mybatis开发dao的方法(5.1SqlSession使用范围_5.2原始dao开发方法)...

5 mybatis开发dao的方法 5.1 SqlSession使用范围 5.1.1 SqlSessionFactoryBuilder 通过SqlSessionFactoryBuilder创建会话工厂SqlSessionFactory 将SqlSessionFactoryBuilder当成一个工具类使用即可&#xff0c;不需要使用单例管理SqlSessionFactoryBuilder。 在需要创建SqlSes…

做⼀个⾼德地图的 iOS / Android MAUI 控件(上)

点击上方蓝字关注我们&#xff08;本文阅读时间&#xff1a;10分钟)Microsoft Build 2022 ⼤会上正式发布了 .NET MAUI , 对于 .NET 开发者可以⽤ C# 完成跨平台的前端应⽤开发。对⽐起 MAUI 的前身 Xamarin , MAUI 除了可以⽤传统的原⽣开发模式外&#xff0c;还⽀持了 Blazor…

易康eCognition Developer 9.01安装教程(附eCognition下载地址及中文教程)

eCognition是由德国Definiens Imaging公司2009年推出的智能化影像分析软件,2010年被美国Trimble公司收购。eCognition是目前所有商用遥感软件中第一个基于目标信息的遥感信息提取软件,它采用决策专家系统支持的模糊分类算法,突破了传统商业遥感软件单纯基于光谱信息进行影像…

C语言试题194之实现strcpy函数功能

📃个人主页:个人主页 🔥系列专栏:C语言试题200例 💬推荐一款刷算法、笔试、面经、拿大公司offer神器👉 点击跳转进入网站 ✅作者简介:大家好,我是码莎拉蒂,CSDN博客专家(全站排名Top 50),阿里云博客专家、51CTO博客专家、华为云享专家 1、题目 题目: 实现st…

[中文版] 可视化 CSS References 文档

本文分享了我将可视化 CSS References 文档翻译成中文版的介绍&#xff0c;翻译工作还在陆续进行中&#xff0c;供学习 CSS 参考。 1. 可视化 CSS References 文档介绍 许多 CSS 的文档都是属性的介绍&#xff0c;而开源项目 css-reference 并没有提供中文版&#xff0c;而当我…

对比 C# 聊聊 C++ 中几类特殊成员函数

一&#xff1a;背景 在 C# 中要说类默认给我们定义的特殊成员函数&#xff0c;莫过于 构造函数&#xff0c;但在 C 中这样的特殊函数高达 6 种&#xff0c;有必要整合一下聊一聊。二&#xff1a;特殊成员函数 1. 默认构造函数和 C# 一样&#xff0c;很多书中都说&#xff0c;如…

Js 枚举定义Layer Icon

layer的icon有7种样式&#xff1a;1-7 [图片来自&#xff1a;https://blog.csdn.net/beauxie/article/details/60959971] 有时候常常记不住 &#x1f623;&#xff0c;不防自己定义一哈&#xff1a; var layerIcon {//无none: -1,//成功success: 1,//失败error: 2,//提问、疑…

前端进阶之路: 前端架构设计(2)-流程核心

可能很多人和我一样, 首次听到"前端架构"这个词, 第一反应是: "前端还有架构这一说呢?" 在后端开发领域, 系统规划和可扩展性非常关键, 因此架构师备受重视, 早在开发工作启动之前, 他们就被邀请加入到项目中, 而且他们会跟客户讨论即将建成的平台的架构要…

C语言试题195之实现strnchr函数功能

📃个人主页:个人主页 🔥系列专栏:C语言试题200例 ✅作者简介:大家好,我是码莎拉蒂,CSDN博客专家(全站排名Top 50),阿里云博客专家、51CTO博客专家、华为云享专家 1、题目 题目: 实现strnchr函数功能 函数名称:在字符串中查找字符 函数原型:char *strnchr(cons…

8.2设备文件及磁盘分区

2019独角兽企业重金招聘Python工程师标准>>> 概览&#xff1a; 设备文件的创建 权限 设备名 类型 主设备号 次设备号 mknod [-m MODE] NAME type [MAJOR MINOR] 创建时&#xff0c;先查看是否存在设备号的冲突 零磁道零扇区是MBR&#xff1a;Maste…

【ArcGIS风暴】ArcGIS求一个矢量图层中多个图斑的“四至点”坐标案例教程

如图所示,为ArcGIS软件自带的全球矢量数据,怎样求取每个大洲(图斑)的四至坐标(xmin、ymin、xmax、ymax)呢? 参考阅读:【ArcGIS遇上Python】python批量获取栅格数据四至(top,bottom,left,right)坐标代码 文章目录 1. 矢量数据加载2. 四至计算结果3. 四至计算过程1.…

一个关于导出excel模板的实例

1 首先jsp页面 点击模板下载&#xff0c;会自动下载模板&#xff45;&#xff58;&#xff43;&#xff45;&#xff4c;&#xff0c;效果如下 让我们看源码&#xff1a; &#xff11; &#xff4a;&#xff53;&#xff50;页面 <div class"tab-pane" id"p…

腾讯视频VIP会员,周卡特价9.5元!

今天给大家推荐特价充值腾讯视频VIP会员的平台——幻海优品&#xff0c;腾讯视频在线直充&#xff0c;VIP会员实时生效&#xff01;腾讯视频VIP会员特价充值周卡&#xff1a;原价12元&#xff0c;特价9.5元月卡&#xff1a;原价30元&#xff0c;特价22元季卡&#xff1a;原价68…

解决安装SQL Server 2005开发版时,出现“SQL Server 服务无法启动 ”点击重试或取消的解决方法

问题描述&#xff1a; 安装SQL Server 2005开发版时&#xff0c;提示SQL Server服务无法启动&#xff0c;有关详细信息&#xff0c;请参阅SQL Server联机丛书中的主题如何查看SQL Server 2005安装日志文件和手动启动SQL Server&#xff0c;如下图所示。 此时&#xff0c;如果点…

C语言试题196之实现strstr函数功能

📃个人主页:个人主页 🔥系列专栏:C语言试题200例 ✅作者简介:大家好,我是码莎拉蒂,CSDN博客专家(全站排名Top 50),阿里云博客专家、51CTO博客专家、华为云享专家 1、题目 题目: 实现strstr函数功能 C 库函数 char *strstr(const char *haystack, const char *nee…

关于数据结构(二)

文章目录[点击展开](?)[] 一UI返回功能思路分析实现方法二当前正在CD技能接着上文<<关于数据结构(一)>>&#xff0c;关于数据结构&#xff0c;在实际的开发中或多或少都有涉及到&#xff0c;只是看自己平时没有积累到。下面是我在项目中的几个实例&#xff1a; 一…

JDBC 之 事务

1.概念&#xff1a;事务指逻辑上的一组操作&#xff0c;组成这组操作的各个单元&#xff0c;要么全部成功&#xff0c;要么全部不成功。 2.数据库开启事务的命令dtl&#xff1a; Start transaction开启事务 Rollback回滚事务&#xff08;撤销&#xff09; Commit提交事务 3.JDB…

[转]后端程序员必备:书写高质量SQL的30条建议

以下文章来源于捡田螺的小男孩 &#xff0c;作者捡田螺的小男孩 转载&#xff1a;《后端程序员必备&#xff1a;书写高质量SQL的30条建议》 前言 本文将结合实例demo&#xff0c;阐述30条有关于优化SQL的建议&#xff0c;多数是实际开发中总结出来的&#xff0c;希望对大家有…