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

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

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

这是一个编译时的属性!

要知道的最重要的事情之一是“特定版本”是一个在编译时生效,而不是在运行时生效的属性。

这是什么一回事呢?

在构build项目时,需要parsing项目的程序集引用,以查找构build系统应该使用的物理程序集。 如果执行“特定版本”检查(请参阅“什么时候是”特定版本“选项”部分),这会影响程序集parsing过程的结果:

  • 构build系统find可能使用的物理组件
  • 构build系统将物理组件的版本与存储在.csproj文件中的程序集版本进行比较,以获取组件的参考
  • 如果两个组件版本完全相同,则parsing过程成功,并且find的物理组件用于构build
  • 如果两个组件版本不匹配,则会丢弃物理组件,并通过查找下一个潜在组件来继续解决过程
  • 如果没有更多的潜在物理组件可以find,解决过程失败。 这会导致编译器警告(警告MSB3245),告诉您无法parsing引用。
  • 有趣的是, 构build然后继续! 如果代码没有对程序集的实际引用,则构build成功(使用前面提到的警告)。 如果代码具有引用,那么构build将失败,并显示错误,看起来好像代码使用未知types或名称空间。 构build真正失败的唯一迹象是警告MSB3245。

订单在哪个组件被解决

程序集parsing过程定位潜在程序集的顺序似乎是这样的:

  1. .csproj文件中由<HintPath>元素引用的程序集
  2. 项目输出path
  3. GAC

请注意,如果GAC中存在多个版本的程序集,则parsing过程将首先尝试parsing为最高版本的程序集。 只有在没有进行“特定版本”检查时,这一点才是重要的。

何时检查“特定版本”?

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

  • <SpecificVersion>元素的存在与否及其值(如果存在的话)
  • 程序集引用中是否存在版本信息

这是一个典型的汇编参考版本信息的样子:

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

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

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

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

  | 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) 

令人惊讶的是,如果<SpecificVersion>和版本信息都不存在,则不执行检查(情况6)。 我会希望检查被执行,并总是失败(与案例2相同),因为在我的理解中, <SpecificVersion>的缺失意味着缺省值“True”。 这可能是我做了testing的Visual Studio 2010的怪癖。

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

“复制本地”的副作用

如果“复制本地”属性设置为“True”,但由于“特定版本”检查而导致程序集parsing过程失败,则不会复制程序集。

参考资料

  • 你需要知道在VS2005中引用程序集 (blogs.msdn.com文章)
  • .NET 2.0中用于assembly和版本控制的新增function (codemag.com文章重现了上面的MSDN文章,直到措辞,但包含一些截图和关于程序集版本的附加信息)

当您添加一个引用时,Visual Studio会在项目文件中logging程序集的[AssemblyVersion]。 这个很重要。 如果你说一年后创build一个错误修正,那么你要确保使用完全相同版本的参考来重build项目,这是一个真正的插入。 如果引用程序集已更改,则会出现错误。

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

了解其后果非常重要,您需要重新部署整个程序以避免事故。 运行时版本不匹配会导致程序崩溃,只能使用.config文件中的<bindingRedirect>进行压缩,这是有风险的。