第 4 步:通过基本代码或探测定位程序集
更新:2007 年 11 月
在使用调用程序集的引用中的信息和配置文件中的信息确定了正确的程序集版本之后,并且在公共语言运行库在全局程序集缓存中进行检查(仅检查具有强名称的程序集)之后,公共语言运行库就会试图查找该程序集。定位程序集的过程包含以下步骤:
如果在应用程序配置文件中找到 <codeBase> 元素,则运行库检查指定的位置。如果找到匹配的程序集,则会使用该程序集,并且不会进行探测。如果在其中没有找到程序集,则绑定请求失败。
然后,运行库使用本节后面指定的规则探测引用的程序集。
说明: |
---|
如果在一个目录中有一个程序集的多个版本,并且要引用该程序集的某个特定版本,则必须使用 <codeBase> 元素而不是 <probing> 元素的 privatePath 属性。如果使用 <probing> 元素,则运行库第一次找到与引用的简单程序集名称匹配的程序集时就会停止探测,而不论这是否是正确的匹配项。如果该程序集是正确的匹配项,则使用它。如果该程序集不是正确的匹配项,则停止探测,绑定失败。 |
通过基本代码定位程序集
通过使用配置文件中的 <codeBase> 元素,可以提供基本代码信息。在运行库尝试探测引用的程序集之前,总会检查此基本代码。如果包含最终版本重定向的发行者策略文件也包含 <codeBase> 元素,则使用该 <codeBase> 元素。例如,如果应用程序配置文件指定一个 <codeBase> 元素,而重写应用程序信息的发行者策略文件也指定一个 <codeBase> 元素,则使用发行者策略文件中的 <codeBase> 元素。
如果在 <codeBase> 元素指定的位置没有找到匹配项,则绑定请求失败,并且不再执行任何步骤。如果运行库确定程序集符合调用程序集的条件,则运行库使用该程序集。当加载由给定的 <codeBase> 元素指定的文件时,运行库进行检查以确保名称、版本、区域性和公钥与调用程序集的引用匹配。
说明: |
---|
应用程序根目录之外的被引用程序集必须具有强名称,并且必须安装在全局程序集缓存中,或者使用 <codeBase> 元素指定。 |
通过探测定位程序集
如果应用程序配置文件中没有 <codeBase> 元素,则运行库使用四个条件来探测程序集:
应用程序基,它是执行应用程序的根位置。
区域性,它是被引用的程序集的区域性属性。
名称,它是被引用的程序集的名称。
<probing> 元素的 privatePath 属性,这是根位置下用户定义的子目录列表。可以使用应用程序域的 AppendPrivatePath 属性,在应用程序配置文件和托管代码中指定此位置。当在托管代码中指定时,先探测托管代码 privatePath,随后探测应用程序配置文件中指定的路径。
探测应用程序基和区域性目录
运行库始终在应用程序基中开始探测,应用程序基可以是一个 URL,也可以是计算机上的应用程序根目录。如果在应用程序基中没有找到引用的程序集,并且未提供区域性信息,则运行库使用程序集名称搜索任何子目录。探测的目录包括:
[application base] / [assembly name].dll
[application base] / [assembly name] / [assembly name].dll
如果指定了引用的程序集的区域性信息,则只探测以下目录:
[application base] / [culture] / [assembly name].dll
[application base] / [culture] / [assembly name] / [assembly name].dll
使用 privatePath 属性进行探测
除区域性子目录和为被引用程序集指定的子目录外,运行库还探测使用 <probing> 元素的 privatePath 属性指定的目录。使用 privatePath 属性指定的目录必须是应用程序根目录的子目录。根据在引用的程序集请求中是否包含区域性信息,探测的目录会有所不同。
运行库在找到第一个与引用的简单程序集名称匹配的程序集时停止探测,无论该匹配正确与否。如果该程序集是正确的匹配项,则使用它。如果该程序集不是正确的匹配项,则停止探测,绑定失败。
如果包含区域性,则探测以下目录:
[application base] / [binpath] / [culture] / [assembly name].dll
[application base] / [binpath] / [culture] / [assembly name] / [assembly name].dll
如果不包含区域性信息,则探测以下目录:
[application base] / [binpath] / [assembly name].dll
[application base] / [binpath] / [assembly name] / [assembly name].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>
探测的其他位置
也可以使用当前的绑定上下文确定程序集的位置。当使用 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 发出请求。