.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.pswp.cn/news/284938.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/284938.shtml
英文地址,請注明出處:http://en.pswp.cn/news/284938.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

C語言試題193之實現strcmp函數功能

??個人主頁:個人主頁 ??系列專欄:C語言試題200例 ??推薦一款刷算法、筆試、面經、拿大公司offer神器?? 點擊跳轉進入網站 ?作者簡介:大家好,我是碼莎拉蒂,CSDN博客專家(全站排名Top 50),阿里云博客專家、51CTO博客專家、華為云享專家 1、題目 題目: 實現st…

淺談Java多線程同步機制之同步塊(方法)——synchronized

在多線程訪問的時候&#xff0c;同一時刻只能有一個線程能夠用 synchronized 修飾的方法或者代碼塊&#xff0c;解決了資源共享。下面代碼示意三個窗口購5張火車票&#xff1a; 1 package com.jikexueyuan.thread;2 /*3 * 未使用synchronized&#xff0c;存在并發4 */5 class…

[轉]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是目前所有商用遙感軟件中第一個基于目標信息的遙感信息提取軟件,它采用決策專家系統支持的模糊分類算法,突破了傳統商業遙感軟件單純基于光譜信息進行影像…

[改善Java代碼]不要覆寫靜態方法

建議33&#xff1a; 不要覆寫靜態方法 我們知道在Java中可以通過覆寫&#xff08;Override&#xff09;來增強或減弱父類的方法和行為&#xff0c;但覆寫是針對非靜態方法&#xff08;也叫做實例方法&#xff0c;只有生成實例才能調用的方法&#xff09;的&#xff0c;不能針對…

C語言試題194之實現strcpy函數功能

??個人主頁:個人主頁 ??系列專欄:C語言試題200例 ??推薦一款刷算法、筆試、面經、拿大公司offer神器?? 點擊跳轉進入網站 ?作者簡介:大家好,我是碼莎拉蒂,CSDN博客專家(全站排名Top 50),阿里云博客專家、51CTO博客專家、華為云享專家 1、題目 題目: 實現st…

ArcGIS實驗教程——實驗四十三:ArcGIS柵格重分類(Reclass)案例詳解

文章目錄 一、重分類1. 新值替代2. 將值組合到一起3. 按相同等級對一組柵格的值進行重分類4. 將特定值設置為NoData 或者為 NoData像元設置某個值二、查找表三、分割四、使用表重分類五、使用ASCI文件重分類重分類就是對原有柵格像元值重新分類從而得到一組新值并輸出。重分類工…

[中文版] 可視化 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…