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.
答案 0 :(得分:8)
可以在.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运行时编译器
除非先前在构建时使用预编译选项编译到项目输出文件夹中,否则在首次访问应用程序时,所有动态内容(aspx,asc,asax,cshtml等)都会在运行时编译一次。此动态内容还可以依赖于其他程序集。 system.web&gt;编译&gt; assemblies元素用于告诉ASP.NET运行时编译器有关这些依赖项的信息,以便它可以引用它们。
ASP.NET运行时编译器将搜索以下位置以便进行这些引用。
请注意,默认情况下,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