.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