.NET誕生以來,程序集的動態加載和卸載都是一個Hack的技術,以前的NetFx都是使用AppDomain的方式去加載程序集,然而AppDomain並無提供直接卸載一個程序集的API,而是要卸載整個AppDomain才能卸載包含在其中的全部程序集。然而卸載整個CurrentAppDomain會使程序不能工做。可能有人另闢西經,建立別一個AppDomain來加載/卸載程序集,可是因爲程序集之間是不能跨域訪問的,也致使只能經過Remote Proxy的方式去訪問,這樣在類型建立和使用上帶來了必定的難度也是類型的繼承變得至關複雜。git
.NET Core中一直沒有AppDomain的支持。可是在.NET Core 3.0中,我最期待的一個特性就是對可收集程序集的支持(Collectible AssemblyLoadContext)。 衆所周知.NET Core中一直使用AssemblyLoadContext的API,來進行程序集的動態加載,可是並無提供Unload的方法,這次升級更新了這方面的能力。github
其實此次AssemblyLoadContext的設計,我認爲更像是Java中ClassLoader的翻版,能夠說很是相似。在使用過程當中自定義AssemblyLoadContext能夠內部管理其中的程序集,並對總體Context進行Unload。使用AssemblyLoadContext也能夠避免程序集名稱和版本的衝突。json
.NET Core 3.0尚未正式版,全部要使用預覽版的SDK完成如下實例。我使用的是.NET Core SDK 3.0.100-preview-009812跨域
dotnet new globaljson --sdk-version 3.0.100-preview-009812
AssemblyLoadContext是一個抽象類的,咱們須要子類化。下面顯示的是咱們建立自定義AssemblyLoadContext的方法,實現一個可回收的Context須要在構造器中指定isCollectible: true :ide
public class CollectibleAssemblyLoadContext : AssemblyLoadContext { public CollectibleAssemblyLoadContext() : base(isCollectible: true) { } protected override Assembly Load(AssemblyName assemblyName) { return null; } }
using System; namespace SampleLibrary { public class SayHello { public void Hello(int iteration) { Console.WriteLine($"Hello {iteration}!"); } } }
var context = new CollectibleAssemblyLoadContext(); var assemblyPath = Path.Combine(Directory.GetCurrentDirectory(),"SampleLibrary.dll"); using (var fs = new FileStream(assemblyPath, FileMode.Open, FileAccess.Read)) { var assembly = context.LoadFromStream(fs); var type = assembly.GetType("SampleLibrary.SayHello"); var greetMethod = type.GetMethod("Hello"); var instance = Activator.CreateInstance(type); greetMethod.Invoke(instance, new object[] { i }); } context.Unload(); GC.Collect(); GC.WaitForPendingFinalizers();
當執行GC收回後,加載的程序集會被徹底的回收。學習
GitHub:https://github.com/maxzhang1985/YOYOFx 若是覺還能夠請Star下, 歡迎一塊兒交流。測試
.NET Core 開源學習羣:214741894spa