.NET在运行时用于定位引用程序集的过程是什么,它与编译期间用于定位引用程序集的过程不同?我对搜索的位置,搜索顺序以及任何可能影响结果的参数/配置设置特别感兴趣。
最佳答案
.NET应用程序中可以进行三种类型的引用。该答案将仅涵盖下面列表中的前两个。
每个参考都必须解决。引用解析是一种以文件形式查找引用的具体实例的过程。解决项目引用的方式与解决文件引用的方式相同。项目引用仅允许您引用尚不存在的程序集(因为它是构建过程的输出)。
重要的是要了解,引用解析在编译时和运行时都会发生,并且两者的过程完全不同。不了解这一点会导致无休止的头痛。相信我,我知道。
运行时参考解析(又名绑定)
调用应用程序时,必须将其加载到内存中。如果应用程序在另一个程序集中使用对象,则该程序集也必须加载到内存中。 .NET框架使用以下过程来执行此操作。
有关更多信息,请参见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>
这里发生了很多事情,我并没有声称要理解所有这些内容,但是我将尝试指出重要的部分。
<private>
元素。 ASP.NET运行时编译器
除非先前在构建时使用pre-compile选项将其编译到项目输出文件夹中,否则所有动态内容(aspx,asc,asax,cshtml等)都在运行时首次访问该应用程序时被编译一次。此动态内容还可以依赖于其他程序集。 system.web>编译>程序集元素用于告知ASP.NET运行时编译器有关这些依赖项的信息,以便它可以引用它们。
ASP.NET运行时编译器将在以下位置搜索这些引用。
请注意,默认情况下,根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/