AssemblyLoadContext
基本上AssemblyLoadContext是AppDomain的继承者,它提供相同而且更多的功能-除了安全边界(隔离)。最小的安全边界是进程,因此你将需要使用进程间通信来正确隔离数据和代码执行。
官网文档中提到Appdomain已经过时了,为了兼容旧的版本,提供了部分功能。建议在.NET Core3.0及更高的版本使用AssemblyLoadContext。
从AppDomain迁移到AssemblyLoadContext
也许你仍在应用程序中使用AppDomain。现在,以下代码显示如何用AssemblyLoadContext的相应方法去替换掉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");
测试封装的获取程序集方法GetAssemblies
准备工作:
创建一个控制台程序
添加一个类库项目,命名为AA.Service
在控制台应用程序,添加一个类TypeFinder代码如下:
public class TypeFinder
{
/// <summary>
/// 获取物理路径
/// </summary>
/// <returns>\bin\Debug\netcoreapp3.0</returns>
public virtual string GetBinDirectory()
{
return AppContext.BaseDirectory;
}
/// <summary>
/// 获取程序集
/// </summary>
/// <returns></returns>
public IList<Assembly> GetAssemblies()
{
var binPath = GetBinDirectory();
var addedAssemblyNames = new List<string>();
var assemblies = new List<Assembly>();
//
foreach (var assembly in AssemblyLoadContext.Default.Assemblies.Where(a=>IsNotSysAssembly(a.FullName)))
{
if (addedAssemblyNames.Contains(assembly.FullName))
continue;
addedAssemblyNames.Add(assembly.FullName);
}
foreach (var dllPath in Directory.GetFiles(binPath, "*.dll",
SearchOption.TopDirectoryOnly))
{
try
{
var an = AssemblyName.GetAssemblyName(dllPath);
if (!addedAssemblyNames.Contains(an.FullName))
{
AssemblyLoadContext.Default.LoadFromAssemblyName(an);
}
}
catch (BadImageFormatException ex)
{
Trace.TraceError(ex.ToString());
}
}
foreach (var assembly in AssemblyLoadContext.Default.Assemblies.Where(a => IsNotSysAssembly(a.FullName)))
{
if (addedAssemblyNames.Contains(assembly.FullName))
continue;
assemblies.Add(assembly);
}
return assemblies;
}
/// <summary>
/// 排除系统程序集
/// </summary>
/// <param name="assemblyName"></param>
/// <returns></returns>
private bool IsNotSysAssembly(string assemblyName)
{
return !assemblyName.StartsWith("Microsoft.")
&& !assemblyName.StartsWith("System.")
&& !assemblyName.StartsWith("Newtonsoft.")
&& assemblyName != "netstandard";
}
}
在控制台应用程序添加引用AA.Service类库,生成查看bin文件,出现了AA.Service.dll
调用代码输出(排除系统dll以Microsoft、system开头的)程序集:
var assemblies= new TypeFinder().GetAssemblies();
foreach (var a in assemblies)
{
Console.WriteLine(a.FullName);
}
输出