How are references located in .NET?

时间:2015-09-01 22:51:02

标签: .net project-reference assembly-references

What process does .NET use to locate a referenced assembly at runtime and is it different than the process used to locate a referenced assembly during compilation? I am specifically interested in the locations that are searched and their search order and any parameters/configuration settings that might affect the outcome.

1 个答案:

答案 0 :(得分:8)

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

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

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

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

    当一个应用程序被调用时,它必须被加载到内存中。如果应用程序使用另一个程序集中的对象,则该程序集也必须加载到内存中。 .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中搜索路径。路径必须与应用程序根目录相关。
    5. 有关详细信息,请参阅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>
      

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

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

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

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

        1. 应用程序私有程序集缓存(又名PAC),它是/ bin文件夹。
        2. GAC(如果使用强名称指定引用)。
        3. 请注意,默认情况下,root web.config使用通配符语法引用PAC中的一些系统程序集和所有程序集。这意味着您很少需要手动向system.web&gt;显式添加引用。编译&gt;组件元素。在许多情况下,您可以而且应该完全删除该元素。它应该只包含对存储在GAC中的程序集的引用。使用Copy Local = true是包含ASP.NET运行时编译器所需的非GAC引用的推荐方法。

          另请注意,如果您使用system.web&gt;,则可能会发生许多细微错误。编译&gt; assemblies元素,使用程序集的强名称指定特定的版本号。 ASP.NET运行时编译器将尝试使用您指定的 exact 版本进行编译。如果在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