引用如何位于.NET中?

Tim*_*ver 3 .net project-reference assembly-references

.NET在运行时使用什么进程来定位引用的程序集,它是否与编译期间用于定位引用程序集的进程不同?我特别感兴趣的是搜索的位置及其搜索顺序以及可能影响结果的任何参数/配置设置.

Tim*_*ver 8

可以在.NET应用程序中进行三种类型的引用.这个答案只涵盖下面列表中的前两个.

  1. 文件参考.
  2. 项目参考
  3. 服务参考.

必须解决每个参考.引用解析是以文件形式定位引用的具体实例的过程.项目引用的解析方式与解析文件引用的方式相同.项目引用只允许您引用尚不存在的程序集(因为它是构建过程的输出.)

重要的是要理解参考解析在编译时和运行时都会发生,并且每个参数的处理完全不同.不理解这一点可能导致无休止的头痛.相信我,我知道.

运行时参考分辨率(又称绑定)

当一个应用程序被调用时,它必须被加载到内存中.如果应用程序使用另一个程序集中的对象,则该程序集也必须加载到内存中..NET框架使用以下过程来执行此操作.

  1. 确定引用的程序集的版本.
    • 引用程序集的版本在编译时写入应用程序清单.除非在配置中被覆盖,否则将使用此版本.
      • 应用程序/ web.config中
      • 发布策略(覆盖application/web.config)
      • machine.config(覆盖发布策略和application/web.config)
  2. 如果先前已加载程序集,则从缓存重新使用.
  3. 如果提供了强名称,请搜索GAC.
  4. 探测
    • 如果指定了codebase元素,则使用.
      • 如果未找到绑定失败.
      • 如果版本,区域性或公钥不匹配,则绑定失败.
    • 搜索应用程序基本路径 匹配简单名称,如果第一次匹配错误版本则失败.
      • 如果没有提供文化,请搜索root然后root/[程序集名称]
      • 如果提供了文化,请搜索root/[culture],然后搜索root/[culture]/[程序集名称].
      • 如果web/app.config指定探测元素,则在privatePath中搜索路径.路径必须与应用程序根相对.

有关更多信息,请参阅http://msdn.microsoft.com/en-us/library/yx7xezcf%28v=vs.110%29.aspx.

编译时间参考分辨率

在构建过程中,MSBuild中会发生编译时间分辨率.MSBuild是Visual Studio和TFS使用的构建引擎.请注意,对于ASP.NET应用程序,首次访问动态组件(aspx,asc,asax,cshtml等)时会发生额外的编译步骤.下面描述这两种情况的参考分辨率.

的MSBuild

程序集解析发生在ResolveAssemblyReferences MSBuild目标中.此目标调用ResolveAssemblyReference任务,将AssemblySearchPaths的值传递给SearchPaths参数,该参数的分配值如下所示.

<PropertyGroup>
        <!--
        The SearchPaths property is set to find assemblies in the following order:

            (1) Files from current project - indicated by {CandidateAssemblyFiles}
            (2) $(ReferencePath) - the reference path property, which comes from the .USER file.
            (3) The hintpath from the referenced item itself, indicated by {HintPathFromItem}.
            (4) The directory of MSBuild's "target" runtime from GetFrameworkPath.
                The "target" runtime folder is the folder of the runtime that MSBuild is a part of.
            (5) Registered assembly folders, indicated by {Registry:*,*,*}
            (6) Legacy registered assembly folders, indicated by {AssemblyFolders}
            (7) Resolve to the GAC.
            (8) Treat the reference's Include as if it were a real file name.
            (9) Look in the application's output folder (like bin\debug)
        -->
    <AssemblySearchPaths Condition=" '$(AssemblySearchPaths)' == ''">
      {CandidateAssemblyFiles};
      $(ReferencePath);
      {HintPathFromItem};
      {TargetFrameworkDirectory};
      {Registry:$(FrameworkRegistryBase),$(TargetFrameworkVersion),$(AssemblyFoldersSuffix)$(AssemblyFoldersExConditions)};
      {AssemblyFolders};
      {GAC};
      {RawFileName};
      $(OutDir)
    </AssemblySearchPaths>
Run Code Online (Sandbox Code Playgroud)

这里有很多事情,我并没有声称理解所有这些,但我会尝试指出重要的部分.

  1. 查找引用的最常见位置是(按搜索顺序)
    • 手动添加到项目的文件(例如/lib/coollib.dll>
    • 由提示路径指定的位置.
    • GAC
    • 应用输出路径.
  2. 标记为Copy Local = true的引用将编译复制到应用程序输出路径.这意味着此设置的值对MSBuild的参考分辨率过程没有影响.请注意,"复制本地UI"设置映射到<private>项目文件中的元素.
  3. 除非指定了特定的version = true,否则MSBuild将始终尝试使用给定程序集可用的最新版本.此设置的默认值为false,这意味着在搜索GAC时,无论项目定义中指定的版本如何,都将始终使用最新版本的DLL.

ASP.NET运行时编译器

除非之前在构建时使用预编译选项编译到项目输出文件夹中,否则在首次访问应用程序时,所有动态内容(aspx,asc,asax,cshtml等)都会在运行时编译一次.此动态内容还可以依赖于其他程序集.system.web> compilation> assemblies元素用于告诉ASP.NET运行时编译器有关这些依赖项的信息,以便它可以引用它们.

ASP.NET运行时编译器将搜索以下位置以便进行这些引用.

  1. 应用程序私有程序集缓存(又名PAC)是/ bin文件夹.
  2. GAC(如果使用强名称指定引用).

请注意,默认情况下,根web.config使用通配符语法引用PAC中的一些系统程序集和所有程序集.这意味着您很少需要手动将引用显式添加到system.web> compilation> assemblies元素.在许多情况下,您可以而且应该完全删除该元素.它应该只包含对存储在GAC中的程序集的引用.使用Copy Local = true是包含ASP.NET运行时编译器所需的非GAC引用的推荐方法.

另请注意,如果使用system.web> compilation> assemblies元素使用程序集的强名称指定特定版本号,则可能会发生许多细微错误.ASP.NET运行时编译器将尝试使用您指定的确切版本进行编译.如果在MSBuild编译阶段针对不同版本的程序集编译应用程序的非动态组件,则会导致问题.这通常是这种情况,因为MSBuild将使用它可以找到的最新版本,如果您设置特定版本= true,则只使用确切版本.

其他资源:

http://jack.ukleja.com/diagnosing-asp-net-page-compilation-errors/ http://blog.fredrikhaglund.se/blog/2008/02/23/get-control-over-your-assembly- dependencies/ https://dhakshinamoorthy.wordpress.com/2011/10/01/msbuild-assembly-resolve-order/ http://www.beefycode.com/post/resolving-binary-references-in-msbuild.aspx