使用公共语言运行库的程序集的所有版本控制都在程序集级别上进行。一个程序集的特定版本和依赖程序集的版本在该程序集的清单中记录下来。除非被配置文件(应用程序配置文件、发行者策略文件和计算机的管理员配置文件)中的显式版本策略重写,否则运行库的默认版本策略是,应用程序只与它们生成和测试时所用的程序集版本一起运行。
说明:仅对具有强命名的程序集进行版本控制。
运行库执行以下几步来解析程序集绑定请求:
1) 检查原程序集引用,以确定该程序集的版本是否被绑定。
2) 检查所有适用的配置文件以应用版本策略。
3) 通过原程序集引用和配置文件中指定的任何重定向来确定正确的程序集,并且确定应绑定到调用程序集的版本。
4) 检查全局程序集缓存和在配置文件中指定的基本代码,然后使用在“运行库如何定位程序集”中解释的探测规则检查该应用程序的目录和子目录。
有关配置应用程序的更多信息,请参见配置文件。有关绑定策略的更多信息,请参见运行库如何定位程序集。
每个程序集都用两种截然不同的方法来表示版本信息:
a) 程序集的版本号,该版本号与程序集名称及区域性信息都是程序集标识的组成部分。该标识将由运行库用来强制实施版本策略,它在运行时的类型解析进程中起着重要的作用。
b) 信息性版本,这是一个字符串,仅为提醒目的而附加版本信息。
每个程序集都有一个版本号作为其标识的一部分。如果两个程序集具有不同的版本号,那么运行库会视它们为完全不同的程序集。此版本号实际表示为具有以下格式的四部分号码:
例如,版本 1.5.1254.0 中的 1 表示主版本,5 表示次版本,1254 表示内部版本号,而 0 则表示修订号。
版本号与其他标识信息(包括程序集名称和公钥,以及与该应用程序所连接的其他程序集的关系和标识有关的信息)一起存储在程序集清单中。
在生成程序集时,开发工具将把每一个被引用程序集的依赖项信息记录在程序集清单中。运行库将这些版本号与管理员、应用程序或发行者设置的配置信息结合使用,以加载被引用程序集的正确版本。
为进行版本控制,运行库会区分常规程序集和具有强命名的程序集。只对具有强命名的程序集执行版本检查。
信息性版本是一个字符串,它仅出于提醒目的将附加的版本信息附加到一个程序集;此信息不在运行时使用。基于文本的信息性版本相当于产品的营销广告、包装或产品名称,不被运行库使用。例如,信息性版本可以是“公共语言运行库版本 1.0”或“NET Control SP 2”。在 Microsoft Windows 中的文件属性对话框的“版本”选项卡上,此信息显示在“产品版本”项中。
说明:虽然可以指定任意文本,但是如果字符串的格式不是程序集版本号使用的格式,或者虽然是这种格式但包含通配符,则在编译时会显示一条警告消息。此警告无碍。
信息性版本用自定义属性 System.Reflection.AssemblyInformationalVersionAttribute 表示。有关信息性版本属性的更多信息,请参见设置程序集属性。
对于大多数 .NET Framework 应用程序而言,您可以在以下位置找到构成该应用程序的程序集,这些位置包括:
1) 该应用程序的目录。
2) 该应用程序目录的子目录。
3) 全局程序集缓存(如果该程序集是共享的话)。
可以通过在配置文件中使用
1) 如果该程序集没有强命名,则使用
2) 如果程序集具有强命名,则
当在使用非托管代码或 COM 互操作应用程序的过程中查找程序集的位置时,类似的规则同样适用:如果该程序集将由多个应用程序共享,则此程序集应被安装到全局程序集缓存中。和非托管代码一起使用的程序集必须作为类型库导出并注册。由 COM 互操作使用的程序集必须在目录中进行注册,尽管有些情况下会自动进行此注册。
并行执行是在同一台计算机上存储和执行多个版本应用程序或组件的能力。这意味着,在同一台计算机上可以同时有运行库的多个版本,并且可以有使用其中某个运行库版本的应用程序和组件的多个版本。并行执行使您能够更多地控制应用程序绑定到的组件版本和应用程序使用的运行库版本。
支持并行存储和执行同一程序集的不同版本是强命名中不可缺少的部分,这种支持内置于运行库基础结构中。因为强命名程序集的版本号是其标识的一部分,所以运行库能够在全局程序集缓存中存储同一程序集的多个版本,并且在运行时加载这些程序集。
尽管运行库使您能够创建并行应用程序,但并行执行并不是自动进行的。
并行 (Side-by-Side) 执行的应用程序和组件的创建指南
1) 将类型标识绑定到文件的特定版本。通过使用具有强命名的程序集,公共语言运行库将类型标识绑定到文件的特定版本。若要创建适用于并行执行的应用程序或组件,您必须为所有的程序集提供强命名。这样可以创建精确的类型标识,可以确保任何类型解析都定向到正确的文件。具有强命名的程序集包含版本、区域性和发行者信息,运行库使用这些信息来正确地定位文件,从而满足绑定请求。
2) 使用可以区别版本的存储。运行库使用全局程序集缓存提供可以区别版本的存储。全局程序集缓存是一个可以区别版本的目录结构,安装在使用 .NET Framework 的每台计算机上。安装在全局程序集缓存中的程序集不会在安装该程序集的新版本时被覆盖。
3) 创建隔离运行的应用程序或组件。隔离运行的应用程序或组件必须管理资源,以避免该应用程序或组件的两个实例在同时运行时发生冲突。应用程序或组件还必须使用版本特定的文件结构。
对于并行执行的应用程序或组件,设计成功的关键是隔离。应用程序或组件必须以隔离方式管理所有的资源,尤其是文件 I/O。请遵循以下准则,确保您的应用程序或组件以隔离方式运行:
1) 按照版本特定的方式,写入注册表。将指示版本的值存储在配置单元或项中,同时,不要在组件的不同版本间共享信息或状态。这就防止了同时运行的两个应用程序或组件覆盖信息。
2) 使命名的内核对象成为版本特定的内核对象,以避免发生争用条件。例如,当来自同一应用程序的两个版本的两个信号灯互相等待时,就发生了争用条件。
3) 使文件名和目录名可以区别版本。这意味着文件结构应该依赖于版本信息。
4) 按照版本特定的方式,创建用户账户和组。应用程序创建的用户账户和组应该由版本识别。不要在应用程序的不同版本间共享用户帐户和组。
在设计并行执行的应用程序时,请遵循这些关于安装和卸载版本的准则:
1) 请不要从注册表中删除在 .NET Framework 的其他版本下运行的其他应用程序可能需要的信息。
2) 请不要在注册表中替换在 .NET Framework 的其他版本下运行的其他应用程序可能需要的信息。
3) 请不要注销 .NET Framework 的其他版本下运行的其他应用程序可能需要的 COM 组件。
4) 对于已注册的 COM 服务器,请不要更改 InprocServer32 或其他注册表项。
5) 请不要删除在 .NET Framework 的其他版本下运行的其他应用程序可能需要的用户账户或组。
6) 请不要向注册表中添加任何包含未版本化路径的内容。
文件版本是运行库不使用的 Win32 版本资源。通常情况下,即使是对于就绪的 QFE,也应更新文件版本。两个相同的文件可以有不同的文件版本信息,而两个不同的文件也可以有相同的文件版本信息。
运行库使用程序集版本进行程序集绑定。若两个相同的程序集版本号不同,则运行库将它们视为两个不同的程序集。
仅当文件版本号更新时,全局程序集缓存工具 (Gacutil.exe) 才允许您替换程序集。安装程序在安装时通常不会覆盖一个程序集,除非该程序集版本号较大。