以下内容抄自Don Box的优秀文章必备.Net。 (可用的here http://my.safaribooksonline.com/0-201-73411-7/ch02lev1sec5#X2ludGVybmFsX0ZsYXNoUmVhZGVyP3htbGlkPTAtMjAxLTczNDExLTcvMjE=)
(恕我直言,这是任何专业 .Net 开发人员必须具备的)
CLR 加载器
CLR 加载器负责加载和初始化程序集、模块、资源和类型。 CLR 加载程序会尽可能少地加载和初始化。与 Win32 加载程序不同,CLR 加载程序不会解析并自动加载从属模块(或程序集)。
相反,只有在实际需要时才按需加载从属部分(与 Visual C++ 6.0 的延迟加载功能一样)。这不仅加快了程序初始化时间,而且减少了正在运行的程序消耗的资源量。
在 CLR 中,加载通常由基于类型的即时 (JIT) 编译器触发。当 JIT 编译器尝试将方法体从 CIL 转换为机器代码时,它需要访问声明类型的类型定义以及类型字段的类型定义。此外,JIT 编译器还需要访问正在 JIT 编译的方法的任何局部变量或参数所使用的类型定义。加载类型意味着加载包含类型定义的程序集和模块。
这种按需加载类型(以及程序集和模块)的策略意味着程序中未使用的部分永远不会进入内存。这还意味着正在运行的应用程序经常会看到随着时间的推移加载新的程序集和模块,因为在执行期间需要这些文件中包含的类型。如果这不是您想要的行为,您有两种选择。一种是简单地声明您想要与加载器显式交互的类型的隐藏静态字段。
加载程序通常会代表您隐式地完成其工作。开发人员可以通过程序集加载器显式地与加载器交互。程序集加载器通过以下方式向开发人员公开LoadFrom
上的静态方法System.Reflection.Assembly
班级。此方法接受 CODEBASE 字符串,该字符串可以是文件系统路径,也可以是标识包含程序集清单的模块的统一资源定位符 (URL)。如果找不到指定的文件,加载器将抛出一个错误System.FileNotFoundException
例外。如果可以找到指定的文件,但不是包含程序集清单的 CLR 模块,则加载程序将抛出System.BadImageFormatException
例外。最后,如果 CODEBASE 是使用除file:
,调用者必须具有 WebPermission 访问权限,否则System.SecurityException
抛出异常。此外,URL 上的程序集除了file:
在加载之前首先下载到下载缓存。
清单 2.2 显示了一个简单的 C# 程序,它加载位于file://C:/usr/bin/xyzzy.dll
然后创建名为的包含类型的实例AcmeCorp.LOB.Customer
。在此示例中,调用者提供的只是程序集的物理位置。
当程序以这种方式使用程序集加载器时,CLR 会忽略程序集的四部分名称,包括其版本号。
示例 2. 2. 使用显式代码库加载程序集
using System;
using System.Reflection;
public class Utilities {
public static Object LoadCustomerType() {
Assembly a = Assembly.LoadFrom(
"file: //C:/usr/bin/xyzzy. dll") ;
return a.CreateInstance("AcmeCorp.LOB.Customer") ;
}
}
尽管按位置加载程序集有些有趣,但大多数程序集都是使用程序集解析器按名称加载的。程序集解析器使用由四部分组成的程序集名称来确定使用程序集加载器将哪个基础文件加载到内存中。如图所示图2.9 http://my.safaribooksonline.com/0-201-73411-7/ch02lev1sec5#X2ludGVybmFsX0ZsYXNoUmVhZGVyP3htbGlkPTAtMjAxLTczNDExLTcvMjM=,这个名称到位置解析过程考虑了多种因素,包括应用程序所在的目录、版本控制策略和其他配置细节(所有这些都将在本章后面讨论)。
程序集解析器通过以下方式向开发人员公开Load
的方法System.Reflection.Assembly
班级。如清单 2.3 所示,此方法接受一个由四部分组成的程序集名称(作为字符串或作为 AssemblyName 引用),表面上看起来与程序集加载器公开的 LoadFrom 方法类似。这种相似性只是表面的,因为 Load 方法首先使用程序集解析器,通过一系列相当复杂的操作来查找合适的文件。这些操作中的第一个是应用版本策略来准确确定应加载所需程序集的哪个版本。
例 2.3。使用程序集解析器加载程序集
using System;
using System.Reflection;
public class Utilities {
public static Object LoadCustomerType() {
Assembly a = Assembly.Load(
"xyzzy, Version=1. 2. 3.4, " +
"Culture=neutral, PublicKeyToken=9a33f27632997fcc") ;
return a.CreateInstance("AcmeCorp.LOB.Customer") ;
}
}