加载过程

JIT编译器将IL代码编译成本地代码时,会查看IL代码援用了哪些类型。在运行时,JIT编译器利用程序集的TypeRef和AssemblyRef元数据表来确定哪一个程序集定义了所援用的类型。在AssemblyRef元数据表的记录项中,蕴含了形成程序集强名称的各个局部。JIT编译器获取所有这些局部:名称(无扩展名和门路)、版本、语言文化、公钥标记(如果被加载的程序集是弱命名的,那么标识中只蕴含:程序集的名称,将不再蕴含版本、语言文化、公钥标记信息),并把它们连接成一个字符串。而后CLR尝试将与该标识匹配的一个程序集加载到AppDomain中(如果还没加载的话)。在外部CLR通过System.Reflection.Assembly类的静态方法Load来尝试加载此程序集(能够显示的将一个程序集加载到AppDomain中)。

Assembly的Load办法
  • 加载强命名程序集

Load办法导致CLR向程序集利用一个版本绑定重定向策略,并在GAC(全局程序集缓存)中查找对应的程序集。如果没找到,就接着去应用程序的基目录、公有门路子目录和codebase地位查找。

  • 加载弱命名程序集

和加载强命名程序集不同的是,Load不会向应用程序利用版本绑定重定向策略,CLR也不会去GAC中查找程序集。

最初如果Load找到指定的程序集,就会返回已加载的程序集的一个Assembly对象的援用,如果没有加载到指定程序集,则会抛出一个System.IO.FileNotFoundException。

AppDomain的Load办法(尽量不应用)

与Assembly的Load办法不同,该办法属于实例办法。作用为将一个程序集加载到一个指定的AppDomain中。可供非托管代码调用,容许宿主将一个程序集注入一个指定的AppDomain。托管代码个别不应用该办法,因为在调用该办法后会开始在惯例地位搜查程序集,而AppDomain关联了一些设置通知CLR如何查找程序集,为了加载程序集CLR将应用与指定AppDomain关联的设置,而不是收回调用的那个AppDomain关联的设置。以及AppDomain的Load办法返回对程序集的一个援用,因为System.Assembly类不是从System.MarshalByRefObject派生的,所以程序集必须按值封送回那个发动调用的AppDomain。当初CLR就会用收回调用的AppDomain的关联设置来定位并加载程序集。如果收回调用的AppDomain没有找到指定的程序集就会抛出FileNotFountException。这不是咱们冀望的行为,所以尽量避免应用AppDomain的Load办法。

Assembly的LoadFrom办法

在外部LoadFrom会先调用System.Reflection.AssemblyName类的静态方法GetAssemblyName,该办法关上指定的文件,查找AssemblyRef元数据表的记录项,提取程序集标识信息,而后返回System.Reflection.AssemblyName对象并敞开文件。随后LoadFrom办法在外部调用Assembly的Load办法,将AssemblyName对象传给它。接着CLR会利用版本绑定重定向策略,并在各个地位查找程序集。如果Load找到了匹配的程序集就会加载并返回已加载程序集的一个Assembly对象,LoadFrom办法将返回这个值。如果没有找到匹配的程序集,LoadFrom就会加载通过LoadFrom的实参传递的门路中的程序集。如果已加载了一个具备雷同标识的程序集,LoadFrom办法会简略返回代表已加载程序集的一个Assembly对象。

*能够给LoadFrom办法传递一个URL实参,CLR会被动下载文件并将其装置到用户的下载缓存中,最初再从那加载文件

Assembly的LoadFile办法

调用这个办法能够从任意门路加载一个程序集,并可将具备雷同标识的一个程序集屡次加载到一个AppDomain中。通过LoadFile加载程序集时,CLR不会主动解析任何依赖问题,代码必须向AppDomain的AssemblyResolve事件注销,让事件回调办法显示加载任何依赖的程序集。

Assembly的ReflectionOnlyLoadFrom办法和ReflectionOnlyLoad办法
  • ReflectionOnlyLoadFrom:加载由门路指定的文件,文件的强名称标识不会获取,也不会再GAC和其它地位搜寻文件。
  • ReflectionOnlyLoad:会在GAC、应用程序基目录、公有门路和codebase指定的地位搜寻指定的程序集。和Load不同的是不会利用版本控制策略,即指定的什么加载版本,取得的便是哪个版本。
  • ReflectionOnlyLoadFrom和ReflectionOnlyLoad:这两个办法加载程序集时,CLR都会禁止程序集中的任何代码执行。试图执行这两个办法加载的程序集中的代码,都会导致CLR抛出InvalidOperationException。
存在多个具备雷同标识的程序集

一台机器上可能共事存在多个具备雷同标识的程序集,因为LoadFrom会在外部调用Load办法,所以CLR有可能不加载你指定的文件,而是加载一个不同的文件,从而达不到预期成果。倡议每次生成程序集都批改版本号,确保每个版本都有本人的惟一标识,进而确保LoadFrom办法能达到预期行为。

程序集卸载

CLR并未提供独自卸载某个程序集的性能,因为一旦这种行为被容许,那么一旦线程从某个办法返回至已卸载的程序集中的代码,应用程序就会解体。要卸载程序集必须卸载程序集所在的整个AppDomain。而应用ReflectionOnlyLoadFrom办法和ReflectionOnlyLoad办法加载的程序集因为程序集中的代码不容许被执行,让人看上去这些程序集是能够卸载的,实际上CLR也不容许卸载这两个办法加载的程序集,因为即使不会运行程序集中的代码但依然能够利用反射来创建对象,援用程序集中定义的元数据,如果程序集被卸载就必须使这些对象有效,从实现复杂度还是执行速度上来讲跟踪这些对象的状态都是得失相当的。