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

时间:2014-02-19 16:04:45

标签: c# .net

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

  

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

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

<dependentAssembly>
  <assemblyIdentity name="*B*" publicKeyToken="..." culture="neutral" />
  <bindingRedirect oldVersion="0.0.0.0-65535.65535.65535.65535" newVersion="1.1.32.0" />
</dependentAssembly>

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

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

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

  

找到的程序集的清单定义与程序集引用

不匹配

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

5 个答案:

答案 0 :(得分:7)

我怀疑是否有可能修复&#34;它就像你想要的那样。如果您阅读该编译错误(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。

答案 1 :(得分:6)

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

我会在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。它更喜欢旧版本,因为它是&#34;主要参​​考&#34;。换句话说,您的项目引用它并且1.1.39.0不太重要,因为它是来自A的间接引用。

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

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

答案 2 :(得分:0)

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

但是,你在这里寻求解决方案,所以我会提出一个建议。缓解这种痛苦的一种可能方法是打包每个单独的DLL解决方案&#34;进入NuGet packages。您不必在NuGet库中发布它们,您可以使用专门的NuGet Feed(例如MyGet)甚至host your own。将文件放入Feed后,管理将正确的版本添加到项目中会更容易一些。

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

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

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

答案 3 :(得分:0)

如果我理解正确,您有遗留程序集A,它引用了程序集B的特定版本。与此同时,您正在构建使用两个程序集的实用程序C - AB

您应该可以按照以下步骤使用同一个程序集B的两个不同版本。不是编译时重定向,但它应该工作:

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

                       

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

    希望它有所帮助!

答案 4 :(得分:0)

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