用于编译的.NET绑定重定向

当我尝试编译一个实用程序时,我收到以下错误,该实用程序使用已部署到我们客户端的文件。

程序集’* A *版本2.0.1.2’使用’* B *版本1.1.39.0’,其版本高于引用程序集’* B *版本1.1.32.0’。

我们的客户端可以使用这些DLL没问题,因为我们有一个绑定的重定向配置文件,它在运行时生效:

    

为了给出一些背景知识,DLL存在于单独的解决方案中,因此一些引用是文件引用而不是项目引用,这只是我必须要忍受的东西!

在编译时是否有适用的等效绑定重定向?

我已经尝试使用调试DLL(版本1.0.0.0)进行编译,源代码回滚到上面的相关版本,但是我在运行时遇到以下错误:

定位的程序集的清单定义与程序集引用不匹配

也许构建服务器的配置与我的机器不同,但无论如何这似乎都不起作用……

我怀疑是否可以根据需要“修复”它。 如果您阅读该编译错误的文档( https://msdn.microsoft.com/en-us/library/416tef0c.aspx ),您将看到您可以更新代码以使用相同的版本,或者在此期间引用这两个版本编译(在您的情况下不是一个选项)。

想象一下,版本1.0.0.0包含方法MyMethod(),但版本1.0.0.1包含MyMethod(字符串),第一个版本由程序集A使用,第二个版本由您正在编译的程序集使用。 您希望编译器如何解决此问题? 在运行时,当您使用绑定重定向时,仍将仅加载一个版本的程序集。 在这里,您不拥有程序集A的代码(您正在引用它,而后者又引用了MyMethod),并且对程序集1.0.0.0的引用嵌入在A的清单中。

长话短说 – 我想只有办法解决它是使用程序集A引用与你相同版本的B。

这是一个非常常见的事故。 Nuget包最有可能是麻烦制造者,log4net和NewtonSoft.Json位于该列表的顶部。 现代版本的MSBuild知道如何解决这个问题。 当您使用工具>选项>项目和解决方案>构建和运行> MSBuild项目构建输出verbosity =详细时,您可以看到的内容。

我会在VS2015上展示它的样子,再现你确切的问题场景。 它开始在ResolveAssemblyReference任务中变得有趣:

 1>Task "ResolveAssemblyReference" ... 1> Primary reference "B, Version=1.1.32.0, Culture=neutral, PublicKeyToken=null". 1> Resolved file path is "c:\projects2\BCopy\bin\Debug\B.dll". 1> Reference found at search path location "{HintPathFromItem}". 1> Found related file "c:\projects2\BCopy\bin\Debug\B.pdb". 1> The ImageRuntimeVersion for this reference is "v4.0.30319". 1> Primary reference "A, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null". 1> Resolved file path is "c:\projects2\A\bin\Debug\A.dll". 1> Reference found at search path location "{HintPathFromItem}". 1> Found related file "c:\projects2\A\bin\Debug\A.pdb". 1> The ImageRuntimeVersion for this reference is "v4.0.30319". 

还有一堆.NET Framework程序集。 在任务结束时,它注意到A依赖于新版本的B:

 1> Dependency "B, Version=1.1.39.0, Culture=neutral, PublicKeyToken=null". 1> Resolved file path is "c:\projects2\B\bin\Debug\B.dll". 1> Reference found at search path location "c:\projects2\B\bin\Debug". 1> For SearchPath "c:\projects2\B\bin\Debug". 1> Considered "c:\projects2\B\bin\Debug\B.winmd", but it didn't exist. 1> Required by "A, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL". 1> Found related file "c:\projects2\B\bin\Debug\B.pdb". 1> This reference is not "CopyLocal" because it conflicted with another reference with the same name and lost the conflict. 1> The ImageRuntimeVersion for this reference is "v4.0.30319". 1> There was a conflict between "B, Version=1.1.32.0, Culture=neutral, PublicKeyToken=null" and "B, Version=1.1.39.0, Culture=neutral, PublicKeyToken=null". 1> "B, Version=1.1.32.0, Culture=neutral, PublicKeyToken=null" was chosen because it was primary and "B, Version=1.1.39.0, Culture=neutral, PublicKeyToken=null" was not. 1> References which depend on "B, Version=1.1.32.0, Culture=neutral, PublicKeyToken=null" [c:\projects2\BCopy\bin\Debug\B.dll]. 1> c:\projects2\BCopy\bin\Debug\B.dll 1> Project file item includes which caused reference "c:\projects2\BCopy\bin\Debug\B.dll". 1> B, Version=1.1.39.0, Culture=neutral, processorArchitecture=MSIL 1> References which depend on "B, Version=1.1.39.0, Culture=neutral, PublicKeyToken=null" [c:\projects2\B\bin\Debug\B.dll]. 1> c:\projects2\A\bin\Debug\A.dll 1> Project file item includes which caused reference "c:\projects2\A\bin\Debug\A.dll". 1> A, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL 1>Done executing task "ResolveAssemblyReference". 

请注意它如何尝试决定是使用版本1.1.32.0还是1.1.39.0。 它更喜欢旧版本,因为它是“主要参考”。 换句话说,您的项目引用它并且1.1.39.0不太重要,因为它是A的间接引用。

该项目建立清洁,没有任何投诉。 为什么这对你不起作用是完全不清楚的,命名你的VS版本非常重要。 我不记得究竟何时添加了这个function,它是不久前的。 在VS2010或VS2012附近。

因此,尝试通过将您在计算机上获得的构建跟踪与我发布的内容进行比较来获得成功。 如果它只是一个普通的旧VS版本问题,那么通过更新它你当然会更加领先。

你的询问的答案是否定的,没有办法在编译时进行绑定重定向。 此时,假设您可以将所有项目引用更新到同一版本(或者在签入源代码控制之前已经这样做),因此构建应该顺利进行。

但是,你在这里寻求解决方案,所以我会提出一个建议。 缓解这种痛苦的一种可能方法是将每个“独立的DLL解决方案” 打包到NuGet包中 。 您不必在NuGet库中发布它们,您可以使用专门的NuGet提要(例如MyGet )或甚至托管您自己的 。 在Feed中包含文件后,管理将正确的版本添加到项目中会更容易一些。

使用NuGet的主要优点是您不需要将二进制文件检查到源代码控制中,因此它们不会与.csproj.vbproj文件中引用的版本号不同步。 如果使用NuGet包还原进行设置,则在编译时将自动安装每个包的正确版本,因此无论构建它的计算机如何,都可以保证以相同的方式构建。

您还可以考虑将一些单独的解决方案整合到单个解决方案/构建过程中,以同步NuGet pacakges之间的版本号/二进制文件,以便很容易判断其中一个版本是否落后于其他版本(因此需要更新)在入住前)。

当然,NuGet并不完美,需要花费一些精力进行设置,即便如此,您仍然可能会遇到一些使版本保持同步的问题,但将它们更新到正确的版本要容易得多。

如果我理解正确,那么您将拥有引用程序集B特定版本的旧程序集A 同时,您正在构建实用程序C ,它使用两个程序集 – AB

您应该能够通过以下步骤使用同一组件B的两个不同版本。 不是编译时重定向,但它应该工作:

  1. 将程序集A引用添加到项目C ,设置SpecificVersion = true ;
  2. 将程序集B版本1.1.39.0引用添加到项目C ,设置SpecificVersion = true ;
  3. 创建一个post build事件,将程序集B 1.1.39.01.1.39.0到项目输出路径/bin/B_1.1.39.0/B.dll ;
  4. 添加以下绑定重定向,并使用codeBase元素为版本1.1.39.0指定程序集B自定义位置;

现在,您的旧程序集A应该感到高兴,因为您的输出文件夹中有程序集B 1.1.32.0版。 您的实用程序C应该很高兴,并且使用程序集B特定版本1.1.39.0并且您已经提供了自定义位置以查找它。

希望能帮助到你!

您可以通过确保从程序集A中包装它们在程序集B之外不可见的方式来包装编译器错误,然后可以依赖于程序集B,使用A到B并使用bindingRedirect来确保程序集A加载正确的DLL版本。 您的里程会有所不同,但确实有效。