.net - .NET中的引用如何定位?

标签 .net project-reference assembly-references

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

最佳答案

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

  • 文件参考。
  • 项目参考
  • 服务参考。

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

    重要的是要了解,引用解析在编译时和运行时都会发生,并且两者的过程完全不同。不了解这一点会导致无休止的头痛。相信我,我知道。

    运行时参考解析(又名绑定)

    调用应用程序时,必须将其加载到内存中。如果应用程序在另一个程序集中使用对象,则该程序集也必须加载到内存中。 .NET框架使用以下过程来执行此操作。
  • 确定引用程序集的版本。
  • 在编译时将引用程序集的版本写入应用程序清单。除非在配置中被覆盖,否则将使用此版本。
  • 应用程序/web.config
  • 发布策略(覆盖application / web.config)
  • machine.config(覆盖发布策略和application / web.config)
  • 如果程序集先前已加载,则从缓存中重新使用。
  • 如果提供了强名,请搜索GAC。
  • 探针
  • 如果指定了codebase元素,则使用。
  • 如果找不到绑定失败。
  • 如果版本,区域性或公共密钥不匹配,则绑定失败。
  • 搜索应用程序基本路径。按简单名称匹配,如果第一个匹配的版本错误,则匹配失败。
  • 如果未提供区域性,请搜索根目录,然后搜索根目录/ [程序集名称]
  • 如果提供了区域性,则搜索root / [culture],然后搜索root / [culture] / [assembly name]。
  • 如果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>
    

    这里发生了很多事情,我并没有声称要理解所有这些内容,但是我将尝试指出重要的部分。
  • 查找参考的最常见位置是(按搜索顺序)
  • 手动添加到项目中的文件(例如/lib/coollib.dll>
  • 提示路径指定的位置。
  • GAC
  • 应用程序输出路径。
  • 标记为Copy Local = true的引用将在编译后复制到应用程序输出路径。这意味着此设置的值在MSBuild的参考解析过程中没有影响。请注意,“复制本地用户界面”设置映射到项目文件中的<private>元素。
  • MSBuild将始终尝试使用给定程序集可用的最新版本,除非指定了特定版本= true。此设置的默认值为false,这意味着在搜索GAC时,无论项目定义中指定的版本如何,都将始终使用DLL的最新版本。

  • ASP.NET运行时编译器

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

    ASP.NET运行时编译器将在以下位置搜索这些引用。
  • 应用程序专用程序集缓存(又名PAC),它是/ bin文件夹。
  • GAC(如果使用强名称指定了引用)。

  • 请注意,默认情况下,根web.config使用通配符语法引用PAC中的一些系统程序集和所有程序集。这意味着几乎不需要您手动将引用显式添加到system.web>编译>程序集元素。在许多情况下,您可以并且应该完全删除该元素。它仅应包含对存储在GAC中的程序集的引用。建议使用Copy Local = true来包括ASP.NET Runtime Compiler所需的非GAC引用。

    还要注意,如果您使用system.web>编译>程序集元素使用程序集的强名称指定特定的版本号,则会发生许多细微的错误。 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

    关于.net - .NET中的引用如何定位?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32342087/

    相关文章:

    c# - 在 C# 中引用 VBA 程序集

    .net - 如何使矩形延伸到整个网格?

    c# - .NET 的 Regex 类和换行符

    .net - 尝试dotnet还原多项目解决方案时无法解决错误

    c# - 在解决方案结构中引用共享项目

    .net - 如何使用 Wix 和项目引用部署 native 镜像 (NGen)

    .net - 什么会导致项目突然忘记其中一个引用?

    c# - 如何在 PdfSharp 中添加指向文件的链接?

    c# - XamlParseException : Could not load file or assembly 'ResourceLibrary, ...' or one of its dependencies. 系统找不到指定的文件

    c# - 错误: Type or namespace not found