C# 如何引用具有相同名称的两个不同DLL?

C# 如何引用具有相同名称的两个不同DLL?,c#,.net,dll,C#,.net,Dll,我正在开发使用Matrox图像库(MIL)的软件。 该软件过去使用MIL的9版,现在我们使用v10。由于向后兼容性,我们必须继续支持v9 使用MIL及其DLL时存在一些困难: 不能同时安装MIL 9和MIL 10。这也没有任何意义 MIL 9和MIL 10的C#dll均命名为Matrox.matroxImaginageLibrary.dll 两个DLL中的名称空间相同 虽然这对于可交换性非常有用(尽管某些函数已经更改),但对于并行使用来说却是一个大问题。 由于文件名和命名空间相同,我无法在同一程

我正在开发使用Matrox图像库(MIL)的软件。
该软件过去使用MIL的9版,现在我们使用v10。由于向后兼容性,我们必须继续支持v9

使用MIL及其DLL时存在一些困难:

  • 不能同时安装MIL 9和MIL 10。这也没有任何意义
  • MIL 9和MIL 10的C#dll均命名为
    Matrox.matroxImaginageLibrary.dll
  • 两个DLL中的名称空间相同
  • 虽然这对于可交换性非常有用(尽管某些函数已经更改),但对于并行使用来说却是一个大问题。
    由于文件名和命名空间相同,我无法在同一程序集中引用两个DLL,因此我为每个DLL创建了一个程序集,
    imaging-system\u mil9

    成像系统\u mil10

    这是必要的,但到目前为止还没有用。我需要的是一个公共程序集中的基类,以便使用继承,因此我创建了程序集
    成像系统

    在这个程序集中,我为MIL命令添加了自己的包装。 这似乎是一个非常好的解决方案,当我最初在安装了MIL9的开发计算机上开发和测试时,效果非常好。当我转移到另一台计算机上,用MIL10进行开发和测试时,我发现包装器中的一些命令需要修改,因为它们在MIL10c#DLL中发生了更改。到目前为止还不错

    今天我回到我的MIL 9电脑,想测试更多的东西,但我的测试程序没能启动,说
    MissingMethodException
    。经过一番搜索,我发现我完全忘记了为一点找到解决方案:相同的文件名:
    我的测试程序参考了
    成像系统
    成像系统_mil9
    成像系统_mil10
    。最后两个都引用了一个文件
    Matrox.matroxImaginageLibrary.dll
    ,因此
    bin
    文件夹中的输出如下所示:

    test.exe
    imaging-system.dll
    imaging-system_mil9.dll
    imaging-system_mil10.dll
    Matrox.MatroxImagingLibrary.dll (the one from MIL 9)
    Matrox.MatroxImagingLibrary.dll (the one from MIL 10)
    
    如您所见,最后两个文件具有相同的名称,因此基本上就像彩票一样,其中一个文件被另一个文件覆盖

    我必须解决这个问题的第一个想法是将文件重命名为
    Matrox.matroxingilibrary9.dll

    Matrox.matroxingilibrary10.dll


    imaging-system\u mil9.dll

    imaging-system\u mil10.dll

    是编译的,因为它们直接引用各自的文件。其中一个
    bin
    文件夹中的输出:

    imaging-system_mil10.dll
    Matrox.MatroxImagingLibrary10.dll
    
    但在编译不直接引用Matrox DLL的程序集时,它会在下一个级别失败。编译器只是跳过重命名的文件,很可能是因为程序集名称与文件名不再匹配。此处的
    bin
    文件夹:

    test.exe
    imaging-system.dll
    imaging-system_mil9.dll
    imaging-system_mil10.dll
    missing: Matrox.MatroxImagingLibrary9.dll, Matrox.MatroxImagingLibrary10.dll
    
    此外,手动将重命名的文件复制到EXE的输出文件夹也没有帮助,因为EXE无法“看到”它们。这是有道理的:假设有1000个DLL,没有一个像程序正在寻找的程序集那样命名。它应该如何找到它?它无法加载所有1000个DLL。。。因此,文件名必须与程序集名称匹配

    我的下一个想法是为Matrox dll设置
    CopyLocal=false
    ,并通过后期构建事件将它们分别复制到
    dll\mil9
    resp中<代码>dll\mil10子文件夹。
    每个程序集都将运行预构建或后构建PowerShell脚本,该脚本复制所有引用dll的所有
    dll
    子文件夹中的所有内容。
    每个EXE将获得一个改编的
    app.config
    文件,如中所述

    问题:我以前没有这样做过,因为没有必要这样做。因此,我目前面临几个问题:
    1)EXE是否会找到正确的Matrox DLL,因为它在搜索子文件夹时会同时看到这两个DLL?DLL具有相同的名称、相同的区域性和相同的publicKeyToken,但版本号不同,因此可以相互区分。
    2)如何在构建过程中获取引用的DLL路径列表,以输入到我的PowerShell脚本中,该脚本将查找
    DLL
    子文件夹并复制文件?
    我想到的唯一方法是读取
    csproj
    文件


    到目前为止我在#1上测试的内容:
    我已经用一个包含控制台EXE和2个DLL的测试解决方案做了几次测试,它们复制了这种情况。 我使用了“CopyLocal=false”和“SpecificVersion=true”,我在
    app.config
    文件中尝试了
    codebase>
    ,但它只适用于一个DLL:

    测试文件夹结构:

    test.exe
    dll\testDLL9.DLL
    dll\testDLL10.DLL
    mil9-x64\mil.net\Matrox.MatroxImagingLibrary.dll
    mil10-x64\mil.net\Matrox.MatroxImagingLibrary.dll
    
    测试EXE:

    private static void Main ()
    {
      Mil10 ();  // when stepping into this, dll\testDLL10.dll is loaded
      Mil9 ();   // when stepping into this, dll\testDLL9.dll is loaded
    }
    
    private static void Mil10 ()  // when arriving here, dll\testDLL10.dll has been loaded
    {
      testDLL10.CDLL10.Work ();   // when stepping into this, mil10-x64\Mil.net\Matrox.MatroxImagingLibrary.dll is loaded
    }
    
    private static void Mil9 ()  // when arriving here, dll\testDLL9.dll has been loaded
    {
      testDLL9.CDLL9.Work ();   // when stepping into this, MissingMethodException is thrown, which is correct, because the EXE uses the already loaded DLL, which is the wrong one.
    }
    
    现在,当首先调用
    Mil9()
    时,它还会加载
    mil10-x64\Mil.net\Matrox.matroxImaginageLibrary.dll

    调用
    testDLL9.CDLL9.Work()
    时,这显然是完全错误的为什么会发生这种情况?
    只有当我删除对
    testDLL10
    的引用并注释掉相关函数时,它才起作用

    app.config:

    <?xml version="1.0" encoding="utf-8"?>
    <configuration>
      <startup>
        <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6" />
      </startup>
      <runtime>
        <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
          <probing privatePath="dll" />
    
          <dependentAssembly>
            <assemblyIdentity name="Matrox.MatroxImagingLibrary"
                              publicKeyToken="5a83d419d44a9d98"
                              culture="neutral" />
            <codeBase version="9.2.1109.1" href="mil9-x64\Mil.net\Matrox.MatroxImagingLibrary.dll" />
          </dependentAssembly>
    
          <dependentAssembly>
            <assemblyIdentity name="Matrox.MatroxImagingLibrary"
                              publicKeyToken="5a83d419d44a9d98"
                              culture="neutral" />
            <codeBase version="10.30.595.0" href="mil10-x64\Mil.net\Matrox.MatroxImagingLibrary.dll" />
          </dependentAssembly>
        </assemblyBinding>
      </runtime>
    </configuration>
    
    
    ,但到目前为止,我不想按照答案第3步中的建议手动加载DLL。我希望CLR为我加载正确的DLL
    
  • 我读过。我不能使用GAC,因为我需要能够通过更改文件夹在不同版本的软件之间切换。尽可能少地连接到操作系统
    • EXE是否会找到正确的Matrox DLL[…]

      对 否,如果使用了
      ,因为这只会将某些文件夹添加到搜索引用的程序集时选中的文件夹列表中。如果找到具有请求名称的文件,则使用此文件。未执行版本检查。如果这是我
      <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
        <dependentAssembly>
          <assemblyIdentity name="Matrox.MatroxImagingLibrary" publicKeyToken="5a83d419d44a9d98" culture="neutral" />
          <bindingRedirect oldVersion="0.0.0.0-10.30.595.0" newVersion="10.30.595.0" />
        </dependentAssembly>
      </assemblyBinding>
      
      'testAPP.vshost.exe' (CLR v4.0.30319: testAPP.vshost.exe): Loaded 'D:\Visual Studio Projects\testTKS_vs2015\testAPP\bin\x64\Debug\dll\testDLL9.dll'. Symbols loaded.
      'testAPP.vshost.exe' (CLR v4.0.30319: testAPP.vshost.exe): Loaded 'D:\Visual Studio Projects\testTKS_vs2015\testAPP\bin\x64\Debug\mil9-x64\Mil.net\Matrox.MatroxImagingLibrary.dll'. Skipped loading symbols. Module is optimized and the debugger option 'Just My Code' is enabled.
      'testAPP.vshost.exe' (CLR v4.0.30319: testAPP.vshost.exe): Loaded 'D:\Visual Studio Projects\testTKS_vs2015\testAPP\bin\x64\Debug\dll\testDLL10.dll'. Symbols loaded.
      'testAPP.vshost.exe' (CLR v4.0.30319: testAPP.vshost.exe): Loaded 'D:\Visual Studio Projects\testTKS_vs2015\testAPP\bin\x64\Debug\mil10-x64\Mil.net\Matrox.MatroxImagingLibrary.dll'. Skipped loading symbols. Module is optimized and the debugger option 'Just My Code' is enabled.
      
      1>------ Build started: Project: testAPP, Configuration: Debug x64 ------
      1>  No way to resolve conflict between "Matrox.MatroxImagingLibrary, Version=10.30.595.0, Culture=neutral, PublicKeyToken=5a83d419d44a9d98" and "Matrox.MatroxImagingLibrary, Version=9.2.1109.1, Culture=neutral, PublicKeyToken=5a83d419d44a9d98". Choosing "Matrox.MatroxImagingLibrary, Version=10.30.595.0, Culture=neutral, PublicKeyToken=5a83d419d44a9d98" arbitrarily.
      1>  Consider app.config remapping of assembly "Matrox.MatroxImagingLibrary, Culture=neutral, PublicKeyToken=5a83d419d44a9d98" from Version "9.2.1109.1" [] to Version "10.30.595.0" [] to solve conflict and get rid of warning.
      1>C:\Program Files (x86)\MSBuild\14.0\bin\Microsoft.Common.CurrentVersion.targets(1820,5): warning MSB3276: Found conflicts between different versions of the same dependent assembly. Please set the "AutoGenerateBindingRedirects" property to true in the project file. For more information, see http://go.microsoft.com/fwlink/?LinkId=294190.
      1>  testAPP -> D:\Visual Studio Projects\testTKS_vs2015\testAPP\bin\x64\Debug\testAPP.exe
      ========== Build: 1 succeeded, 0 failed, 2 up-to-date, 0 skipped ==========
      
        <!-- probing privatePath="dll" /-->
        <dependentAssembly>
          <assemblyIdentity name="testDLL9" culture="neutral" />
          <codeBase version="1.0.0.0" href="dll\testDLL9.dll" />
        </dependentAssembly>
        <dependentAssembly>
          <assemblyIdentity name="testDLL10" culture="neutral" />
          <codeBase version="1.0.0.0" href="dll\testDLL10.dll" />
        </dependentAssembly>