本文提供了此 API 参考文档的补充说明。
这个AssemblyLoadContext 表示加载上下文。 从概念上讲,加载上下文创建一个用于加载、解析和可能卸载一组程序集的范围。
AssemblyLoadContext 主要用于提供程序集加载隔离。 它允许在同一个进程中加载同一程序集的多个版本。 它将替换 .NET Framework 中多个 AppDomain 实例提供的隔离机制。
注释
- AssemblyLoadContext 不提供任何安全功能。 所有代码都具有进程的完整权限。
- 在 .NET Core 2.0 - 2.2 中, AssemblyLoadContext 是一个抽象类。 若要在这些版本中创建具体类,请实现该方法 AssemblyLoadContext.Load(AssemblyName) 。
运行时中的使用情况
运行时实现两个程序集加载上下文:
- AssemblyLoadContext.Default 表示运行时的默认上下文,该上下文用于应用程序主程序集及其静态依赖项。
- 该Assembly.LoadFile(String)方法通过实例化最基本的AssemblyLoadContext来隔离它加载的程序集。 它具有一种简单隔离方案,它以自己的 AssemblyLoadContext 方式加载每个程序集,且不进行依赖项解析。
应用程序使用情况
应用程序可以创建自己的 AssemblyLoadContext 解决方案,以便为高级方案创建自定义解决方案。 自定义侧重于定义依赖项解析机制。
AssemblyLoadContext 提供两个扩展点来实现托管程序集解析:
- 方法 AssemblyLoadContext.Load(AssemblyName) 为 AssemblyLoadContext 提供了解析、加载和返回程序集的首次机会。 如果AssemblyLoadContext.Load(AssemblyName)方法返回
null
,加载程序将尝试将程序集加载到AssemblyLoadContext.Default中。 - AssemblyLoadContext.Default如果无法解析程序集,则原始AssemblyLoadContext程序集获得第二次解析该程序集的机会。 运行时引发 Resolving 事件。
此外, AssemblyLoadContext.LoadUnmanagedDll(String) 虚拟方法允许自定义默认非托管程序集解析。 默认实现返回 null
,这会导致运行时搜索使用其默认搜索策略。 默认搜索策略足以满足大多数方案。
技术挑战
无法在单个进程中加载多个版本的运行时。
谨慎
加载多个副本或不同版本的框架程序集可能会导致意外和难以诊断的行为。
小窍门
使用进程边界进行远程处理或进程间通信来解决此隔离问题。
程序集加载的计时可能会使测试和调试变得困难。 程序集通常会加载,而不会立即解析其依赖项。 依赖项将根据需要加载。
- 当代码分支到依赖程序集时。
- 代码加载资源时。
- 当代码显式加载程序集时。
AssemblyLoadContext.Load(AssemblyName)实现可以添加可能需要隔离的新依赖项,以允许不同的版本存在。 最自然的实现会将这些依赖项置于默认上下文中。 仔细的设计可以隔离新的依赖项。
同一程序集多次加载到不同的上下文中。
- 这可能会导致令人困惑的错误消息,例如“无法将类型为‘Sample.Plugin’的对象强制转换为‘Sample.Plugin’”。
- 跨隔离边界封送处理很复杂。 典型的解决方案是使用仅加载到默认加载上下文的程序集中定义的接口。