自定义版本策略
.NET允许管理员覆写默认的程序集解析策略,和提供自定义的版本绑定策略。可以为单独的应用程序提供自定义策略,而只影响一个具体应用程序对于私有或共享程序集的绑定。也可以提供本机范围内的自定义策略,作用于本机每个应用程序绑定到GAC中指定共享程序集的方式。管理员可以因为各种原因而选择创建自定义策略,但是通常进行这些工作,是在一个新的或改进的服务端程序集版本提交使用,并且提供商保证兼容较早版本的情况下进行。.NET默认的版本绑定和解析策略总是试图读取与客户端应用程序一起编译的“正确”版本。如果较新版本覆写较早版本的强命名私有副本,那么程序集解析器会仍会尝试读取较早的与之一起编译的版本,并在读取失败时抛出异常,即使新版本已经被安装到GAC中。为了处理这些情况,.NET允许管理员重定向请求的版本到不同的版本。.NET也允许管理员指定一个查找特定版本的具体位置,来取代默认的位置(首先是GAC,然后是应用程序目录)。这样管理员就可以在其他应用程序中利用现有私有程序集,或者重定向程序集在GAC中的读取位置。
应用程序自定义策略
.NET配置工具有一个被称为“应用程序”的顶层文件夹。如果要为一个应用程序提供自定义策略,那么就把它添加到该文件夹中(右键点击“应用程序”文件夹,选择添加.NET程序文件)。添加后的应用程序将包含一个称为“已配置的程序集”的子文件夹。点击该文件夹,在.NET配置工具的右侧面板中就会显示已配置的程序集,和是否已为这些程序集创建了自定义版本绑定或基于代码的策略:
“已配置的程序集”文件夹中包括了所有该应用程序使用的且拥有自定义策略的程序集。如果要为一个程序集提供自定义策略,那么就必须添加到该文件夹中(右键点击“已配置的程序集”文件夹,选择添加.NET程序集文件):
可以从GAC或应用程序使用的所有程序集列表中(该列表通过读取应用程序清单生成)选择要配置的程序集。注意,既然该列表显示了所有使用的程序集,那么也就包含了只具有友好命名的私有程序集,选择它们是没有意义的,因为当程序集没有强命名时程序集解析器会忽略版本问题。在列表中可以很容易的分辨程序集是否具有强命名:强命名程序集在公共密钥标记列中存在值:
自定义版本绑定策略
一旦选择一个程序集后,.NET配置工具会立即显示出该程序集的属性。在绑定策略标签中即可指定自定义版本绑定策略。标签中包括任意版本的重定向列表。 管理员可以指定一个具体的版本重定向到另一个具体的版本,或者指定一个重定向的版本范围,也可以指定一个新版本重定向到老版本(例如在新版本中发现了一个缺陷)。惟一的要求就是要以.NET的版本号格式Major.Minor.Build.Revision来指定版本号。管理员可以添加任意多个所需要的版本重定向请求。
自定义基本代码策略
在程序集属性的基本代码标签中,管理员可以定向程序集解析器应在哪里查找程序集的具有版本:
管理员可以重定向对于私有或共享程序集的请求到任意位置。例如,如果程序集解析器要求读取一个程序集的3.2.1.0版本而这个版本存在基本代码重定向,那么解析器会在重定向的位置查找该程序集版本,即使在私有目录或GAC中存在合适的版本。同样地,惟一的要求是以.NET的版本号格式指定版本号,以及以URL的格式指定位置。管理员可以添加任意多个所需要的基本代码重定向请求。
应用程序配置文件
当对一个应用程序提供自定义策略时,使用.NET配置工具定义的配置信息会保存在应用程序文件夹中的一个特殊配置文件中。这个文件被成为<application name>.config。该配置文件中以XML的格式包含了自定义策略信息。该配置文件允许在多台机器上复制应用程序自定义策略:
全局自定义策略
管理员也可以对GAC中的程序集提供全局自定义策略。从GAC添加程序集到.NET配置工具的“已配置的程序集”文件夹中,然后为程序集指定自定义版本绑定和基本代码重定向。指定的方式与给单个应用程序指定自定义策略的方式一样。需要注意的是全局自定义策略会作用于本机上的所以应用程序。此外,全局自定义策略是应用于下游的,就是说应用程序会首先应用自己的自定义策略,后应用全局自定义策略。例如,假设一个应用程序以一个类库的1.0版本生成。应用程序安装了一个自定义策略请求2.0版本来代替1.0版本。此外,假设在本机上存在一个全局自定义策略重定向2.0版本请求到类库的3.0版本。那么,当应用程序在该描述场景下运行时,它会使用该类库的3.0版本。
当提供一个全局自定义策略时,使用.NET配置工具定义的配置信息会保存在一个作用于整个计算机的特殊配置文件中,这个文件被成为machine.config。路径为<Windows Folder>\Mircrosoft.Net/Frameowork\<version number>\CONFIG文件夹。该配置文件中同样以XML包含了全局自定义策略,并允许在多台机器上复制应用程序自定义策略。
CLR版本
.NET版本兼容的严格性和强制性引出了一个很有趣的问题:如果一个应用程序以.NET的2.0版本生成,当.NET的3.0版本可用时,该应用程序将不会利用3.0版本的改进。原因是应用程序清单中包含了所以依赖程序集的版本号,包括CLR和应用程序框架。.NET程序集是强命名的,因此程序集解析器会坚持正确版本的匹配。为了克服自身程序集的版本兼容问题,.NET必须提供了一套不同的基本规则,所涉及的问题错综复杂 。通过类库或EXE中的组件使用的CLR的正确版本可能是多样的,它依赖于与之编译的版本,可用的.NET版本,以及应用程序版本策略。
.NET构架试图在创建新版本和支持现有应用程序之间取得一个平衡。最终,它决定由应用程序提供商来决定是否支持一个具体的CLR版本。这标志着一个观念的改变:微软不再绝对保证向前和向后兼容。相应地,微软承诺尽一切努力将向后兼容,并会指出哪里是不兼容的。这就意味着一个新的.NET版本不会完全向后兼容。 这项保证的一个例外是安全性——微软为了处理安全漏洞会故意在.NET新版本中作出变动。
CLR的并行执行
即然CLR和各个.NET应用程序框架由许多程序集组成,那么它们可以被视为一个单独的版本单元。这些单位的多个版本可以在任意计算机上共存,这被称为CLR“side-by-side execution(并行执行)”。并行执行是可行的,是因为.NET部署在GAC中,而且GAC支持同一程序集的多个版本的并行执行。所以不同的.NET应用程序可以同时使用.NET的不同版本。也可以安装.NET的新版本或移除现有版本。并行的方式降低了当安装一个应用程序而影响另一个的可能性,因为较早的应用程序仍然可以使用较早的.NET版本。即使如此,.NET并行执行是允许选择何时升级到下个.NET版本,而不是让它脱离最新的CLR 版本。
版本的统一化
所有的.NET应用程序都寄宿于一个读取CLR DLLs的非托管进程中。该非托管进程可以使用每个CLR程序集的正确版本。此外,CLR的版本号支配哪个.NET应用程序框架版本可以使用,因为它们被视为一个单独的版本单元。事实上.NET总是在一个統一的框架程序集堆栈中运行,称为“version unification(版本統一化)”。統一化的要求是因为CLR和.NET应用程序框架不是为混合和匹配而设计的,就是说,不可以一些程序集来自1.1版本而一些版本来自2.0版本。
通常情况下,一个.NET应用程序包括一个单独的EXE应用程序程序集用于启动进程,并且将潜在的多个其他程序集读取到进程中。统一化就意味着在一个进程中包括一个托管应用程序,EXE应用程序程序集和它读取的程序集都使用同一.NET版本。该进程中是由用于启动进程的EXE来选择CLR和应用程序框架的版本; 而其他读取的程序集无权过问。例如,在.NET(.NET 1.0)第一次发布中的所有程序集的版本号都是1.0.3300.0。在.NET(.NET 1.1)第二次发布中的所有程序集的版本号都是1.1.5000.0。假如一台计算机上同时安装了这两个版本。当一个EXE程序集使用.NET的1.1.5000.0版本时,通过它读取的所有程序集都会使用1.1.5000.0版本,即使它们是使用1.0.3300.0版本编译的。这样是没有问题的,因为.NET1.1是向后兼容1.0版本的。但是,反过来如果EXE程序集选择了1.0.3300.0版本,通过它读取的所有程序集都会使用1.0.3300.0版本,即使它们需要1.1.5000.0版本的新特性。这样就可能导致应用程序发生故障。
注意,避免使用自定义版本绑定策略来覆写同一化。他会导致不可确定的结果。
指定一个CLR版本
在一台给定的计算机上,可以有任意CLR版本组合。应用程序可以隐式依赖与默认的版本决定策略,或者可以显式地提供配置信息指示支持的CLR版本。
默认版本绑定
如果一个应用程序没有指示.NET需要哪个版本的CLR,那么应用程序就是实际上告知.NET任何兼容的CLR版本都是允许使用的。在这种情况下,.NET会检测与应用程序编译的CLR版本,并使用本机上最新的CLR兼容版本。为此,.NET必须知道哪个CLR版本是与其他版本向后兼容的。现在,微软认为所有新的.NET版本应是向后兼容的。注意CLR向后兼容与向前兼容不一样。向后兼容处理的是一个以较早版本编译的程序集是否可以在较新版本上执行的问题。向前兼容处理的是一个以较新版本编译的程序集是否可以在较老版本上执行的问题。向后兼容是主要变动产品对类型定义和类型的行为。向前兼容是通过元数据版本来控制。.NET 1.0和.NET 1.1拥有同样的元数据版本,所以他俩之间同时向后和向前兼容。.NET 2.0拥有一个新的元数据版本,所以它只考虑向后兼容——.NET 2.0程序集需要.NET 2.0运行时。
下边这个表描述了CLR版本兼容矩阵。左侧列列出了与程序集编译的CLR版本,其余列列出了这些程序集是否可以在其他CLR版本上运行:
Assembly\CLR version | 1.0 | 1.1 | 2.0 |
1.0 | + | + | + |
1.1 | + | + | + |
2.0 | - | - | + |
在注册表中维护着一个相似的兼容表。当.NET决定将哪一个.NET版本提供给应用程序时会使用该表(默认使用最高可用的兼容版本)。
指定支持的CLR版本
使用默认版本可能导致应用程序运行于未经测试的CLR版本,而导致不可确定的行为。如果不想应用程序依赖于默认的版本绑定策略,并且拥有确定的行为,那么可以提供显式的版本配置。在这种情况下,应用程序必须在其配置文件中使用带有supportedRuntime属性的startup标签指示哪一个CLR版本是它支持的:
通常来讲,不应将没有通过测试和验证环节的CLR版本添加到该列表中,以确保版本的兼容性。CLR 版本列出的顺序表明使用的优先权。.NET会尝试提供第一个CLR版本给应用程序。如果该版本在本级上是不可用的,.NET会继续尝试列表中的下个版本。如果指定的版本没有一个可用,.NET会拒绝读取应用程序,并显示一个消息框要求用户安装在配置文件中指定的最近的一个支持版本。注意,startup会指示覆写任何.NET可以提供的默认行为,这就意味着即使另一个兼容版本在本机上是可用的,如果它没有在配置文件中列出,.NET会拒绝在该版本上允许应用程序。
根据原版英文翻译,所以不足和错误之处请大家不吝指正,谢谢:)