使用 COM 互操作解决反射中的 .NET 程序集不匹配问题

Resolving .NET assembly mismatches in reflection with COM interop

我正在尝试在 .Net 2.0 可执行文件中使用 .Net 4.6 库。

我使用了 this COM approach,它一直有效,直到程序集 System.Collections.Immutable 被解决。

我收到带有消息 "Could not load file or assembly 'System.Collections.Immutable, Version=1.2.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a' or one of its dependencies. The located assembly's manifest definition does not match the assembly reference. (Exception from HRESULT: 0x80131040)"

的 ReflectionTypeLoadException

.Net 4.6 库使用 Roslyn 和 Roslyn 程序集引用 System.Collections.Immutable,版本 =1.2.1.0。并且项目中引用了这个版本的程序集。但是 Roslyn 程序集(Microsoft.CodeAnalysis.CSharp、版本 2.6.0.0)引用 System.Reflection.Metadata、版本=1.4.1.0 和元数据程序集引用 System.Collections.Immutable、版本=1.2.0.0

当我在 .Net 4.6 可执行文件而不是 .Net 2.0 中使用 .Net 4.6 库时,一切正常,无一例外。

我尝试将不可变程序集的 "Specific Version" 设置为 false,但没有用。 还尝试将 .Net 2.0 和 .Net 4.6 文件夹分开,但都不起作用。 .Net 4.6 库 dll 和 Immutable dll 也在同一个文件夹中。

app.config .Net 2.0 可执行文件

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <runtime>
    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
      <probing privatePath="Adapter" />
    </assemblyBinding>
  </runtime>
</configuration>

app.config .Net 4.6 库

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <runtime>
    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
      <dependentAssembly>
        <assemblyIdentity name="System.Collections.Immutable" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
        <bindingRedirect oldVersion="0.0.0.0-1.2.1.0" newVersion="1.2.1.0" />
      </dependentAssembly>
      ......other dependent assemblies....
    </assemblyBinding>
  </runtime>
</configuration>

.Net 2.0 可执行代码

static void Main()
{
    Console.WriteLine("CLR version from EXE: {0}", Environment.Version);
    Console.WriteLine("Is64BitProcess: {0}", (IntPtr.Size == 8));

    Type myClassAdapterType = Type.GetTypeFromProgID("Net4ToNet2Adapter.MyClassAdapter");
    object myClassAdapterInstance = Activator.CreateInstance(myClassAdapterType);
    IEnchanterAdapter myClassAdapter = (IEnchanterAdapter)myClassAdapterInstance;
    myClassAdapter.DoNet4Action();
}

.Net 4.6 库代码

[ComVisible(true)]
[Guid("E36BBF07-591E-4959-97AE-D439CBA392FB")]
public interface IMyClassAdapter
{
    void DoNet4Action();
}

[ComVisible(true)]
[Guid("A6574755-925A-4E41-A01B-B6A0EEF72DF0")]
public class MyClassAdapter : IMyClassAdapter
{
    private MyClass _myClass = new MyClass();

    public MyClassAdapter()
    {
        Console.WriteLine("adapter constructor");
    }

    public void DoNet4Action()
    {
        Console.WriteLine("CLR version from EXE: {0}", Environment.Version);
        Console.WriteLine("Is64BitProcess: {0}", Environment.Is64BitProcess);

        _myClass.DoNet4Action();
    }
}

class MyClass
{
    public void DoNet4Action()
    {
        var workspace = new AdhocWorkspace(); // throws exception here
    }
}

输出

CLR version from EXE: 2.0.50727.8794
Is64BitProcess: True
adapter constructor
CLR version from EXE: 4.0.30319.42000
Is64BitProcess: True

Fusion Assembly 绑定日志(项目引用版本 1.2.2.0 时的)(这再次适用于 .Net 4.6 可执行文件)

        FusionLog   "=== Pre-bind state information ===
LOG: DisplayName = System.Collections.Immutable, Version=1.2.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a\n (Fully-specified)
LOG: Appbase = file:///D:/Develop/Enchanter/UnityWorkspace/bin/Debug/
LOG: Initial PrivatePath = NULL
Calling assembly : Microsoft.CodeAnalysis, Version=2.6.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35.
===
LOG: This bind starts in default load context.
LOG: Using application configuration file: D:\Develop\Enchanter\UnityWorkspace\bin\Debug\UnityWorkspace.exe.Config
LOG: Using host configuration file: 
LOG: Using machine configuration file from C:\Windows\Microsoft.NET\Framework64\v4.0.30319\config\machine.config.
LOG: Post-policy reference: System.Collections.Immutable, Version=1.2.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
LOG: Attempting download of new URL file:///D:/Develop/Enchanter/UnityWorkspace/bin/Debug/System.Collections.Immutable.DLL.
LOG: Attempting download of new URL file:///D:/Develop/Enchanter/UnityWorkspace/bin/Debug/System.Collections.Immutable/System.Collections.Immutable.DLL.
LOG: Attempting download of new URL file:///D:/Develop/Enchanter/UnityWorkspace/bin/Debug/Adapter/System.Collections.Immutable.DLL.
WRN: Comparing the assembly name resulted in the mismatch: Build Number
ERR: Failed to complete setup of assembly (hr = 0x80131040). Probing terminated.
"   string

程序集绑定重定向应该添加到 .Net 2.0 可执行文件手动因为Visual Studio不会自动这样做由于 COM 互操作,它们没有关系。

.Net 2.0 可执行文件的新 app.config 是:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <runtime>
    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
      <probing privatePath="Adapter" />
      <dependentAssembly>
        <assemblyIdentity name="System.Collections.Immutable" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
        <bindingRedirect oldVersion="0.0.0.0-1.2.2.0" newVersion="1.2.2.0" />
      </dependentAssembly>
       ......other dependent assemblies....
    </assemblyBinding>
  </runtime>
</configuration>