.Net dll多个同名的程序集版本冲突共存与通过基本代码或探测定位程序集方案

.Net dll多个同名的程序集版本冲突共存与通过基本代码或探测定位程序集方案

 

在使用调用程序集的引用中的信息和配置文件中的信息确定了正确的程序集版本之后,并且在公共语言运行时在全局程序集缓存中进行检查(仅检查具有强名称的程序集)之后,公共语言运行时就会尝试查找该程序集。 定位程序集的过程包含以下步骤:

  1. 如果在应用程序配置文件中找到 <codeBase> 元素,则运行时会检查指定的位置。 如果找到匹配的程序集,则会使用该程序集,并且不会进行探测。 如果在其中没有找到程序集,则绑定请求失败。

  2. 然后,运行时使用本节后面指定的规则探测引用的程序集。

说明

如果在一个目录中有一个程序集的多个版本,并且要引用该程序集的某个特定版本,则必须使用 <codeBase> 元素而不是 <probing> 元素的 privatePath 特性。 如果使用 <probing> 元素,则运行时第一次找到与引用的简单程序集名称匹配的程序集时就会停止探测,而不论这是否是正确的匹配项。 如果该程序集是正确的匹配项,则使用它。 如果该程序集不是正确的匹配项,则停止探测,绑定失败。

通过基本代码定位程序集

通过使用配置文件中的 <codeBase> 元素,可以提供基本代码信息。 在运行时尝试探测引用的程序集之前,总会检查此基本代码。 如果包含最终版本重定向的发行者策略文件也包含 <codeBase> 元素,则使用该 <codeBase> 元素。 例如,如果应用程序配置文件指定一个 <codeBase> 元素,而重写应用程序信息的发行者策略文件也指定一个 <codeBase> 元素,则使用发行者策略文件中的 <codeBase> 元素。

如果在 <codeBase> 元素指定的位置没有找到匹配项,则绑定请求失败,并且不再执行任何步骤。 如果运行时确定程序集符合调用程序集的条件,则运行时使用该程序集。 当加载由给定的 <codeBase> 元素指定的文件时,运行时进行检查以确保名称、版本、区域性和公钥与调用程序集的引用匹配。

 说明

应用程序根目录之外的被引用程序集必须具有强名称,并且必须安装在全局程序集缓存中,或者使用 <codeBase> 元素指定。

通过探测定位程序集

如果应用程序配置文件中没有 <codeBase> 元素,则运行时使用以下四个条件来探测程序集:

  • 应用程序基,它是执行应用程序的根位置。

  • 区域性,它是被引用的程序集的区域性特性。

  • 名称,它是被引用的程序集的名称。

  • <probing> 元素的 privatePath 特性,这是根位置下用户定义的子目录列表。 可以使用应用程序域的 AppendPrivatePath 属性,在应用程序配置文件和托管代码中指定此位置。 当在托管代码中指定时,先探测托管代码 privatePath ,随后探测应用程序配置文件中指定的路径。

探测应用程序基和区域性目录

运行时始终在应用程序基中开始探测,应用程序基可以是一个 URL,也可以是计算机上的应用程序根目录。 如果在应用程序基中没有找到引用的程序集,并且未提供区域性信息,则运行时使用程序集名称搜索任何子目录。 探测的目录包括:

   [应用程序基] / [程序集名称].dll

   [应用程序基] / [程序集名称] / [程序集名称].dll

如果指定了引用的程序集的区域性信息,则只探测以下目录:

   [应用程序基] / [区域性] / [程序集名称].dll

   [应用程序基] / [区域性] / [程序集名称] / [程序集名称].dll

使用 privatePath 特性进行探测

除区域性子目录和为被引用程序集指定的子目录外,运行时还探测使用 <probing> 元素的 privatePath 特性指定的目录。 使用 privatePath 特性指定的目录必须是应用程序根目录的子目录。 根据在引用的程序集请求中是否包含区域性信息,探测的目录会有所不同。

运行时在找到第一个与引用的简单程序集名称匹配的程序集时停止探测,无论该匹配正确与否。 如果该程序集是正确的匹配项,则使用它。 如果该程序集不是正确的匹配项,则停止探测,绑定失败。

如果包含区域性,则探测以下目录:

   [应用程序基] / [bin 路径] / [区域性] / [程序集名称].dll

   [应用程序基] / [bin 路径] / [区域性] / [程序集名称] / [程序集名称].dll

如果不包含区域性信息,则探测以下目录:

   [应用程序基] / [bin 路径] / [程序集名称].dll

   [应用程序基] / [bin 路径] / [程序集名称] / [程序集名称].dll

探测示例

给定以下信息:

  • 引用的程序集名称:myAssembly

  • 应用程序根目录:http://www.code.microsoft.com

  • 配置文件中的 <probing> 元素指定:bin

  • 区域性:de

运行时探测以下 URL:

   http://www.code.microsoft.com/de/myAssembly.dll

   http://www.code.microsoft.com/de/myAssembly/myAssembly.dll

   http://www.code.microsoft.com/bin/de/myAssembly.dll

   http://www.code.microsoft.com/bin/de/myAssembly/myAssembly.dll

多个同名的程序集

下面的示例说明了如何对多个同名的程序集进行配置。


<dependentAssembly>
      <assemblyIdentity name="Server" publicKeyToken="c0305c36380ba429" /> 
         <codeBase version="1.0.0.0" href="v1/Server.dll"/>
         <codeBase version="2.0.0.0" href="v2/Server.dll"/>
   </dependentAssembly>

 


为使运行库可在计算机配置文件或出版商策略文件中使用 <codeBase> 设置,该文件还必须重定向程序集版本。应用程序配置文件可在不重定向程序集版本的情况下拥有基本代码设置。确定要使用的程序集版本后,运行库应用确定版本的文件中的基本代码设置。如果未指示基本代码,运行库便以常用的方式寻找程序集。

如果程序集具有强名称,则基本代码设置可以是本地 Intranet 或 Internet 上的任何地方。如果程序集为私有程序集,则基本代码设置必须是相对于应用程序目录的路径。


于没有强名称的程序集,则忽略版本,并且加载程序使用 <dependentAssembly> 内出现的第一个
<codebase>。如果应用程序配置文件中具有将绑定重定向到另一个程序集的项,则即使该程序集版本与绑定请求不匹配,重定向仍具有优先
权。

探测的其他位置

也可以使用当前的绑定上下文确定程序集的位置。 当使用 Assembly.LoadFrom 方法并且在 COM 互操作方案中时,通常会发生这种情况。 如果程序集使用 LoadFrom 方法引用另一个程序集,则可以将调用程序集的位置作为在何处查找引用的程序集的提示。 如果找到匹配项,则加载该程序集。 如果未找到匹配项,运行时就会继续其搜索语义,然后请求 Windows Installer 提供程序集。 如果提供的程序集与绑定请求均不匹配,则引发异常。 如果引用一种类型,则此异常为托管代码中的 TypeLoadException ;如果没有找到要加载的程序集,则此异常为 FileNotFoundException

例如,如果 Assembly1 引用 Assembly2,而 Assembly1 是从 http://www.code.microsoft.com/utils 下载的,则可以将该位置作为查找 Assembly2.dll 的提示。 然后,运行时在 http://www.code.microsoft.com/utils/Assembly2.dll 和 http://www.code.microsoft.com/utils/Assembly2/Assembly2.dll 中探测程序集。 如果在这两个位置均未找到 Assembly2,则运行时向 Windows Installer 发出请求。

posted on 2014-06-17 15:07  icycore  阅读(727)  评论(0编辑  收藏  举报

导航