.Net Core 程序集管理说明(加载)
.NET CORE 的程序集加载管理和以前的 .NET 发生了很大的变化, 在 .NET CORE 里, 程序集的加载, 依赖了 xx.deps.json 文件, deps.json 文件里,定义了程序所需有的所有程序集以前程序集之间的依赖关系。
所以如果程序集的信息没有定义在 deps.json 文件里, 程序集是不会加载的。
程序集的依赖关系,可以通过 DependencyContext 类来处理, 通过 Load(程序集) 的方式,来获取程序集的依赖信息, 但是这个 DependencyContext 类也是通过加载 deps.json 文件里的程序, 如有个程序集叫 a.dll 文件, 那就就需要定义一个 a.deps.json 文件, 如果没有定义这个文件, 那么 DependencyContext.Load 将返回 null。
下面为一段 System.Data.Odbc 程序集的定义:
"System.Data.Odbc/4.7.0": { "dependencies": { "Microsoft.NETCore.Platforms": "3.1.0" }, "runtime": { "lib/netstandard2.0/System.Data.Odbc.dll": { "assemblyVersion": "4.0.2.0", "fileVersion": "4.700.19.56404" } }, "runtimeTargets": { "runtimes/freebsd/lib/netcoreapp2.0/System.Data.Odbc.dll": { "rid": "freebsd", "assetType": "runtime", "assemblyVersion": "4.0.2.0", "fileVersion": "4.700.19.56404" }, "runtimes/linux/lib/netcoreapp2.0/System.Data.Odbc.dll": { "rid": "linux", "assetType": "runtime", "assemblyVersion": "4.0.2.0", "fileVersion": "4.700.19.56404" }, "runtimes/osx/lib/netcoreapp2.0/System.Data.Odbc.dll": { "rid": "osx", "assetType": "runtime", "assemblyVersion": "4.0.2.0", "fileVersion": "4.700.19.56404" }, "runtimes/win/lib/netcoreapp2.0/System.Data.Odbc.dll": { "rid": "win", "assetType": "runtime", "assemblyVersion": "4.0.2.0", "fileVersion": "4.700.19.56404" } }, "compile": { "ref/netstandard2.0/System.Data.Odbc.dll": {} } }
此段定义了 system.data.odbc 程序集的依赖, 以前程序集在每个平台运行的目标程集, 还有编译时的程序集。通过 DependencyContext 都可以获取到这些信息:
CompileLibraries: 编译时的库
RuntimeLibraries:运行时的库
RuntimeLibraries 返回的都是一个 RuntimeLibrary 对象集合, RuntimeLibrary 对象又可以通过 RuntimeAssemblyGroups 属性来获取 runtimeTargets 节点的属性。
奇怪的时 DependencyContext 没有获取依赖库的信息, 通过 CompileLibraries 获取不到依赖的库信息, 上面虽然有定义,但是在测试的时候还是返回为 null。竟然通过 DependencyContext 获取不到引用的程序集, 就通过 Assembly 对象的 GetReferencedAssemblies 方法来获取。
.NET CORE 在加载程序集的时候,只会加载程序集本身, 而不会去加载引用的程序集,而在程序集使用到引用的程序集时, 才会去判断是否有加载, 这个加载过程就是通过 AssemblyLoadContext 的 Resolving 事件来加载, 当 .NET CORE 程序在运行的时候,遇到一个没有加载过的程序集,则会引发 Resolving 事件,这个事件里必须返回一个 Assembly 对象, 如果返回 null 则会提示程序集加载失败。
.NetCore 默认处理了 Resolving 事件,通过入口 程序集的 deps.json 信息来加载, 所以没有在 deps.json 文件中定义的程序集是不会加载的。
可以看一下 AssemblyLoadContext 类的官方文档,文档内容比简单,通过好多测试才明白 Resolving 事件。