.net 程序集引用的“特定版本”属性在 Visual Studio 中究竟是如何工作的?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/24022134/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-03 12:45:11  来源:igfitidea点击:

How exactly does the "Specific Version" property of an assembly reference work in Visual Studio?

.netvisual-studio

提问by herzbube

Today I had a closer look at the "Specific Version" property of assembly references in Visual Studio 2010. After a few experiments with unexpected results I set out to learn as much as possible about how the property works. Even SO, it appears to me, does not have all the answers, so here is my attempt at self-answering the question:

今天,我仔细研究了 Visual Studio 2010 中程序集引用的“特定版本”属性。经过几次实验并获得意想不到的结果后,我开始尽可能多地了解该属性的工作原理。在我看来,即使是这样,也没有所有的答案,所以这是我自我回答问题的尝试:

How exactlydoes the "Specific Version" property of an assembly reference work in Visual Studio?

程序集引用的“特定版本”属性在 Visual Studio 中究竟是如何工作的?

回答by herzbube

It's a compile-time property!

这是一个编译时属性!

One of the most important things to know is that "Specific Version" is a property that takes effect at compile-timeand notat runtime.

其中一个知道的最重要的事情是,“特定版本”是,需要在效果的属性编译时运行时。

What is it all about?

这是什么一回事呢?

When a project is built, the project's assembly references need to be resolved in order to find the physical assemblies that the build system should use. If the "Specific Version" check is performed (see section "When is "Specific Version" checked?"), it affects the outcome of the assembly resolution process:

构建项目时,需要解析项目的程序集引用,以便找到构建系统应使用的物理程序集。如果执行“特定版本”检查(请参阅“何时检查“特定版本”?”部分),它会影响程序集解析过程的结果:

  • The build system locates a physical assembly that it can potentially use
  • The build system compares the physical assembly's version to the assembly version stored in the .csproj file for the assembly reference
  • If the two assembly versions are exactly the same, the resolution process succeeds and the physical assembly found is used for the build
  • If the two assembly versions do not match, the physical assembly is discarded and the resolution process continues by locating the next potential assembly
  • If no more potential physical assemblies can be located, the resolution process fails. This results in a compiler warning (warning MSB3245) that tells you that the reference could not be resolved.
  • Interestingly enough, the build then continues!If the code has no actual references to the assembly, the build succeeds (with the previously mentioned warning). If the code has references, the build fails with an error that looks as if the code were using unknown types or namespaces. The only indication why the build reallyfailed is the warning MSB3245.
  • 构建系统定位它可能使用的物理程序集
  • 构建系统将物理程序集的版本与 .csproj 文件中存储的程序集版本进行比较以供程序集参考
  • 如果两个程序集版本完全相同,则解析过程成功,找到的物理程序集用于构建
  • 如果两个程序集版本不匹配,则丢弃物理程序集,并通过定位下一个潜在程序集继续解析过程
  • 如果找不到更多潜在的物理程序集,则解析过程将失败。这会导致编译器警告(警告 MSB3245)告诉您无法解析引用。
  • 有趣的是,构建然后继续!如果代码没有对程序集的实际引用,则构建成功(带有前面提到的警告)。如果代码有引用,则构建失败并显示错误,看起来好像代码使用了未知类型或命名空间。构建真正失败的唯一迹象是警告 MSB3245。

Order in which assemblies are resolved

解决程序集的顺序

The order in which the assembly resolution process locates potential assemblies appears to be this:

程序集解析过程查找潜在程序集的顺序似乎是这样的:

  1. The assembly referenced by the <HintPath>element in the .csproj file
  2. The project output path
  3. The GAC
  1. <HintPath>.csproj 文件中的元素引用的程序集
  2. 项目输出路径
  3. 海关总署

Note that if several versions of the assembly exist in the GAC, the resolution process first attempts to resolve to the assembly with the highest version. This is important only if the "Specific Version" check is not made.

请注意,如果 GAC 中存在多个版本的程序集,则解析过程首先尝试解析具有最高版本的程序集。这仅在未进行“特定版本”检查时才重要。

When is "Specific Version" checked?

什么时候勾选“特定版本”?

Visual Studio bases its decision whether to perform the "Specific Version" check on two pieces of information found in the .csproj file:

Visual Studio 根据在 .csproj 文件中找到的两条信息来决定是否执行“特定版本”检查:

  • The presence or absence of the <SpecificVersion>element, and its value (if it is present)
  • The presence or absence of version information in the assembly reference
  • <SpecificVersion>元素的存在与否,及其值(如果存在)
  • 程序集引用中是否存在版本信息

This is how a typical assembly reference with version information looks like:

这是带有版本信息的典型程序集引用的样子:

<Reference Include="Foo, Version=1.2.3.4, Culture=neutral, processorArchitecture=MSIL">
  <SpecificVersion>True</SpecificVersion>
  <HintPath>..\..\Bar\Foo.dll</HintPath>
</Reference>

And this is how the assembly reference looks like withoutversion information:

这就是没有版本信息的程序集引用的样子:

<Reference Include="Foo">
[...]

The following table shows when the "Specific Version" check is performed, and when it is not.

下表显示了何时执行“特定版本”检查,何时不执行。

                            |     Version information
                            |  Present       Not present
----------------------------+------------------------------
<SpecificVersion>           |
- Present, has value True   |    Yes (1)        Yes (check always fails) (2)
- Present, has value False  |    No  (3)        No (4)
- Not present               |    Yes (5)        No (6)

The surprising thing here is that no check is performed if both <SpecificVersion>and version information are absent (case 6). I would have expected the check to be performed and to always fail (same as case 2) because in my understanding the absence of <SpecificVersion>implies the default value "True". This may be a quirk of Visual Studio 2010 where I did my tests.

这里令人惊讶的是,如果<SpecificVersion>和 版本信息都不存在(情况 6),则不会执行检查。我本来希望检查被执行并且总是失败(与情况 2 相同),因为在我的理解中,没有<SpecificVersion>意味着默认值“True”。这可能是我进行测试的 Visual Studio 2010 的一个怪癖。

When you examine the properties of an assembly reference in the Visual Studio UI (select the reference and hit F4), the value you see for the "Specific Version" property tells you whether or not Visual Studio is going to perform the "Specific Version" check. In case 6 the UI will show "True", although the <SpecificVersion>element is not present in the .csproj file.

当您在 Visual Studio UI 中检查程序集引用的属性时(选择引用并按 F4),您看到的“特定版本”属性值会告诉您 Visual Studio 是否将执行“特定版本”查看。在情况 6 中,UI 将显示“True”,尽管<SpecificVersion>.csproj 文件中不存在该元素。

Side-effects on "Copy local"

“复制本地”的副作用

If the "Copy Local" property is set to "True" but the assembly resolution process fails because of the "Specific Version" check, no assembly is copied.

如果“Copy Local”属性设置为“True”但程序集解析过程因“特定版本”检查而失败,则不会复制任何程序集。

Reference material

参考资料

回答by Hans Passant

When you add a reference then Visual Studio records the [AssemblyVersion] of the assembly in the project file. This is important. If you, say, create a bug fix a year later then you want to make sure that you rebuild the project with the exactsame version of the reference so it is a true drop-in. You'll get an error if the reference assembly has changed.

添加引用时,Visual Studio 会在项目文件中记录程序集的 [AssemblyVersion]。这个很重要。例如,如果您在一年后创建错误修复程序,那么您要确保使用完全相同的参考版本重建项目,以便它是真正的插入。如果参考程序集已​​更改,您将收到错误消息。

But that isn't always desirable. Some programmers let the assembly version automatically increment, generating a new version every single time they rebuild. Even though the public interface of the assembly never changed. Some configure their project by using Nuget to obtain libraries and let it automatically update the library when there's a new release available. They will like to set the Specific Version property to False to suppress the compile error.

但这并不总是可取的。一些程序员让程序集版本自动递增,每次重建时都会生成一个新版本。即使程序集的公共接口从未改变。有些人通过使用 Nuget 获取库来配置他们的项目,并在有新版本可用时让它自动更新库。他们希望将特定版本属性设置为 False 以抑制编译错误。

Pretty important to understand the consequence, you do need to redeploy the entire build of the program to avoid accidents. Version mismatches at runtime crash the program and can only be suppressed with a <bindingRedirect>in the .config file which is risky.

了解后果非常重要,您确实需要重新部署程序的整个构建以避免事故。运行时版本不匹配会导致程序崩溃,并且只能使用<bindingRedirect>.config 文件中的a 来抑制,这是有风险的。