.net 如何构建/部署需要同一程序集的多个版本的项目?

.net 如何构建/部署需要同一程序集的多个版本的项目?,.net,visual-studio,assemblies,.net,Visual Studio,Assemblies,我正在处理一个使用conflict.dll版本6.2的项目,但该项目也使用使用conflict.dll版本5.8的helper.dll 我可以将6.2和5.8安装到GAC中,但我希望这个项目xcopy是可部署的。我相信.net会在应用程序bin目录中搜索程序集,如下所示: \bin\conflict.dll(6.2) \bin\5.8\conflict.dll(5.8) 但此时,如何在项目中添加对两个版本的conflict.dll的引用,然后如何确保旧的conflict.dll部署到\bin\5

我正在处理一个使用conflict.dll版本6.2的项目,但该项目也使用使用conflict.dll版本5.8的helper.dll

我可以将6.2和5.8安装到GAC中,但我希望这个项目xcopy是可部署的。我相信.net会在应用程序bin目录中搜索程序集,如下所示: \bin\conflict.dll(6.2) \bin\5.8\conflict.dll(5.8)

但此时,如何在项目中添加对两个版本的conflict.dll的引用,然后如何确保旧的conflict.dll部署到\bin\5.8?我是创建构建操作还是有其他方法

谢谢

我相信.net会搜索 应用程序箱中的程序集 类似这样的目录:\bin\conflict.dll (6.2)\bin\5.8\conflict.dll(5.8)

不,这是错误的。我建议你阅读这篇文章来了解更多关于什么

也就是说,您不能在同一应用程序域中加载同一程序集的两个不同版本。您可以将同一程序集的不同版本加载到同一应用程序域中,但这是并且应该避免的。在您的情况下,这意味着您必须选择要使用的冲突程序集的版本。您有两个选择:

  • 重新编译
    helper.dll
    以使用最新版本的
    conflict.dll
    (如果我有
    helper.dll
    的源代码,我肯定会使用这个版本)
  • 选择所需的
    conflict.dll
    版本,并在配置文件中应用。例如,如果要使用最新版本:

    <runtime>
        <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
            <dependentAssembly>
                <assemblyIdentity name="conflict"
                                  publicKeyToken="xxxxxxxxx"
                                  culture="neutral" />
                <bindingRedirect oldVersion="5.8.0.0" 
                                 newVersion="6.2.0.0" />
            </dependentAssembly>
        </assemblyBinding>
    </runtime>
    
    
    
  • 这将有效地指示CLR在尝试解析
    helper.dll
    的引用时加载
    conflict.dll的版本6.2。请注意,如果两个版本使用不同的密钥进行强签名,则此技术将不起作用。显然,由于
    helper.dll
    是针对5.8版编译的,如果您有任何差异(缺少方法、不同的方法签名),则在尝试调用冲突的方法时会出现运行时异常,因此只有在您完全确定要做什么的情况下才能执行此操作


    结论:无论你决定走哪条路,你都必须在bin文件夹中
    xcopy
    一个
    冲突.dll的单一版本

    为了支持Darin的答案,当然你需要消除这种多版本的问题。他使用绑定重定向的解决方案是一个很好的方案-+1。我可以提供一个解决方案,如果绝对必要的话,它允许您保留这两个选项,但是您必须编写一些代码

    这里唯一真正的问题是,两个部署的文件名必须相同,才能由加载程序默认拾取。您可能会进行非常可怕的欺骗,只需将5.8 dll部署为
    Conflict.exe
    ,这样它就可以并排放置
    Conflict.dll
    (以及更新版本),您就会发现它是有效的

    此外,请按照Darin的答案中的链接进行操作。基于此文件的内容,您可以简单地将5.8 dll部署到bin\content\content.dll中,当运行时搜索它时,它将自动查找此子文件夹

    但是,这不是一个好的解决方案:)

    编辑-新解决方案

    如果Conflict.dll的两个版本都已签名,您是否确实尝试过使用稍微不同的名称部署其中一个版本?我刚刚设置了一个winforms应用程序,其中包含对同一(签名)程序集的不同版本的两个程序集引用。这会导致生成中出现几个问题,因为最后引用的版本将部署到bin文件夹,而另一个不会(因此您必须手动复制这两个版本;相应地重命名其中一个)。然后我试着运行这个应用程序,它会显示一个包含两个常量字符串的消息框;程序集的每个版本各有一个。它工作得非常好

    -不要构建它(否则必须进行文件重命名);只需打开表单应用程序的bin\debug文件夹并运行exe

    ClassLibrary1.dll和ClassLibrary1Vanything.dll是程序集的v1.0.0.0和v2.0.0.0,在其他方面具有相同的名称和公钥。尽管classlibrary1vanything.dll的文件名错误,但它仍然可以工作(可能是因为它已签名)

    在app.config中,我确实输入了一个代码库提示,并认为这就是它工作的原因(最初我将它部署为不同的文件名),但后来我注释掉了它,它仍然工作。当程序集必须部署到子文件夹或完全不同的位置时,代码库可能最有用

    原文

    我试着让第二个选项起作用,但它似乎不想起作用

    毫无疑问,有一些聪明的方法可以开箱即用,但由于我还没有聪明到找到它(现在),我会改为修饰并使用前面提到的支持主题中显示的第三个选项,并钩住应用程序域的
    AssemblyResolve
    事件

    如果为要绑定到不同文件名的程序集的全名添加自己的配置(可能只是在appSettings中),那么在AssemblyResolve事件处理程序中,您可以查阅要加载的程序集的名称,以查看它是否在您的配置中。如果是,请抓住该位置并使用Assembly.LoadFrom加载它

    因此,一旦您准备好了类似的内容,您只需在其中添加冲突v5.8程序集名称的条目以及应用程序应使用的文件名

    我不知道您正在部署什么类型的应用程序,但在win窗体中,控制台应用程序和服务
    AppDomain.CurrentDomain.BaseDirectory
    将等于bin f
    <runtime>
      <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
        <dependentAssembly>
          <assemblyIdentity name="Conflict" publicKeyToken="111111111111" />
          <codeBase version="1.0.0.0" href="bin\Conflict\v1\Conflict.dll" />
          <codeBase version="2.0.0.0" href="bin\Conflict\v2\Conflict.dll" />
        </dependentAssembly>
      </assemblyBinding>
    </runtime>