【C#】AssemblyLoadContext 加載程序集


使用 .NET Core 3.0 的 AssemblyLoadContext 實現插件熱加載

一般情況下,一個 .NET 程序集加載到程序中以后,它的類型信息以及原生代碼等數據會一直保留在內存中,.NET 運行時無法回收它們,如果我們要實現插件熱加載 (例如 Razor 或 Aspx 模版的熱更新) 則會造成內存泄漏。在以往,我們可以使用 .NET Framework 的 AppDomain 機制,或者使用解釋器 (有一定的性能損失),或者在編譯一定次數以后重啟程序 (Asp.NET 的 numRecompilesBeforeAppRestart) 來避免內存泄漏。

因為 .NET Core 不像 .NET Framework 一樣支持動態創建與卸載 AppDomain,所以一直都沒有好的方法實現插件熱加載,好消息是,.NET Core 從 3.0 開始支持了可回收程序集 (Collectible Assembly),我們可以創建一個可回收的 AssemblyLoadContext,用它來加載與卸載程序集。

AssemblyLoadContext存在主要用於提供程序集加載隔離,不提供Appdomain中的安全邊界(隔離),.net core安全邊界(隔離)由進程負責。 它允許在單個進程中加載同一程序集的多個版本。 它將替換 .NET Framework 中的多個實例提供的隔離機制 AppDomain

.net core 程序 默認的采用AssemblyLoadContext.Default 加載程序依賴項。

因此我們可以通過AssemblyLoadContext.Default.Assemblies。來獲取當前程序集的所有的依賴項。

AppDomain方法:

  • 獲取所有程序集
過時:var assembliesInAppDomain = AppDomain.CurrentDomain.GetAssemblies(); 新:var assembliesInAssemblyLoadContext = AssemblyLoadContext.Default.Assemblies;
  • 加載一個程序集
過時:AppDomain.CurrentDomain.Load(AssemblyName.GetAssemblyName("path")); 新:AssemblyLoadContext.Default.LoadFromAssemblyName(AssemblyName.GetAssemblyName("path"));
  • 加載一個程序集 路徑或者字節數組:
過時:AppDomain.CurrentDomain.Load(File.ReadAllBytes("path")); 新:AssemblyLoadContext.Default.LoadFromStream(File.OpenRead("path")); // or AssemblyLoadContext.Default.LoadFromAssemblyPath("path");

 新建一個Context並且把程序集加載進 這個Context中

 AssemblyLoadContext pluginAssemblyLoadContext = new("pluginAssemblyLoadContext", true);//輸入Context名稱,指定是否可以卸載
 Assembly assembly = pluginAssemblyLoadContext.LoadFromAssemblyPath(item);

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM