托管程序集与具有不同阶段的算法一起定位并加载。
除附属程序集和 WinRT 程序集之外的所有托管程序集都使用相同算法。
何时加载托管程序集?
触发托管程序集加载的最常用机制是静态程序集引用。 每当代码使用另一个程序集中定义的类型时,编译器都插入这些引用。 根据运行时的需要加载这些程序集 (load-by-name)。 未指定加载静态程序集引用的时间的确切时间。 它可能因运行时版本而异,并且受内联等优化的影响。
直接使用以下 API 也会触发加载:
重要
与 .NET Framework 不同,参数assemblyFileAssembly.LoadFrom在 .NET 中被视为文件路径,而不是 URI。 在 .NET Framework 中,可以传递文件 URI(例如 file:///C:/path/to/assembly.dll)——这类 URI 是由 Assembly.CodeBase 构造而成的,并且程序集会成功加载。 在 .NET 环境中,assemblyFile 值被传递给 Path.GetFullPath,由于无法正确处理 URI,导致加载失败。 如果已有文件 URI 字符串,请先创建一个 Uri 实例并使用其 LocalPath 属性获取文件路径,然后再调用 Assembly.LoadFrom。 若要获取已加载程序集的文件路径,请使用 Assembly.Location 而不是 CodeBase。
算法
以下算法描述运行时如何加载托管程序集。
确定
activeAssemblyLoadContext。- 对于静态程序集引用,
activeAssemblyLoadContext 是加载引用程序集的实例。 - 首选 API 使
activeAssemblyLoadContext 显式。 - 其他 API 推断
activeAssemblyLoadContext。 对于这些 API,使用 AssemblyLoadContext.CurrentContextualReflectionContext 属性。 如果其值为null,则使用推断 AssemblyLoadContext 的实例。 - 请参阅“ 何时加载托管程序集?”部分中的 表。
- 对于静态程序集引用,
对于
Load-by-name方法,activeAssemblyLoadContext以以下优先级顺序的方式加载程序集:- 检查其
cache-by-name。 - 调用 AssemblyLoadContext.Load 函数。
-
AssemblyLoadContext.Default检查实例的缓存并运行托管程序集默认探测逻辑。 如果新加载程序集,则会将引用添加到 AssemblyLoadContext.Default 实例的
cache-by-name中。 - 引发活动 AssemblyLoadContext 的 AssemblyLoadContext.Resolving 事件。
- 引发 AppDomain.AssemblyResolve 事件。
- 检查其
对于其他类型的加载,按
activeAssemblyLoadContext 以下优先级顺序加载程序集:- 检查其
cache-by-name。 - 如果
active是AssemblyLoadContext,请运行AssemblyLoadContext.Default。 - 从指定的路径或原始程序集对象加载。 如果程序集是新加载的,则会向
activeAssemblyLoadContext 实例的cache-by-name添加一个引用。
- 检查其
在任何一种情况下,如果程序集被新加载,则会引发AppDomain.AssemblyLoad事件。