向 C# COM 服务器添加一些内容并从 C++ 使用它而无需重新编译

Add something to a C# COM server and use it from C++ without recompiling

让我们假设

  • I'm working for company A and I provide a C# DLL called managed.dll which is COM visible. I provide as well the TLB file called managed.tlb.
  • a company B is using my managed.dll in a C++ EXE called unmanaged.exe.
  • a customer C has to get the managed.dll from my company A and the unmanaged.exe from company B. The reason for that is that company B is not allowed to redistribute the managed.dll from company A.

现在假设我在我的 managed.dll 中的一个 类 中添加了一个方法或 属性。那么B公司的unmanaged.exe就坏了。公司 B 必须使用较新的 tlb 文件重新编译它。

当我向 managed.dll 添加内容时,如何避免公司 B 必须重新编译他们的 unmanaged.exe

我问的原因是

  • I've no control when company B is recompiling or releasing their unmanaged.exe. Even if I provide my managed.dll to company B every time I've added something.
  • I've no control which versions of the managed.dll and unmanaged.exe the customer C is using.
  • company B would like to claim that their unmanaged.exe V1.0 is working with my managed.dll V1.0 or newer.

我们怎样才能做到这一点?

我的 managed.dll 的源代码是这样的:

[Guid("852e5991-ddcc-56dd-8e13-90dcaf11ebe5")]
[ComVisible(true)]
public interface ITestA
{
    string DummyString();
    int DummyInt();
}

[Guid("41916928-6bea-43de-bedb-318df340e7b8")]
[ComVisible(true)]
[ComDefaultInterface(typeof(ITestA))]
public class TestA : ITestA
{
    public string DummyString() { return "Dummy"; }
    public int DummyInt() { return 123; }
}

tlb 文件是用 RegAsm.exe managed.dll /tlb /codebase 生成的。

unmanaged.exe 的源代码如下所示:

#include "stdafx.h"
#import "managed.tlb"
using namespace std;
int _tmain(int argc, _TCHAR* argv[])
{
    HRESULT hr = CoInitialize(NULL); // Init COM
    IClassAPtr pClassA(__uuidof(ClassA));
    // and so on ...
}

问候沃尔米奇

Microsoft 定义 IHTMLEventObj6 是有原因的。这是 IHTMLEventObj 的第 5 次增量更新。您需要做同样的事情:ITestA2 需要继承 ITestA 并添加额外的方法。

事实证明,如果我想向 managed.dll 添加新方法或属性,我必须提供新接口(如 ITestA2、ITestA3 等)。

所以 managed.dll 的源代码可以这样扩展:

[Guid("5ff6c41a-6e4c-4d96-8e5e-72a560715b56")]
[ComVisible(true)]
public interface ITestA2
{
    string DummyString();
    int DummyInt();
    bool DummyBool(); // new method
}

[Guid("d5b8f4b5-d33f-4e7d-866c-ef0844216a3a")]
[ComVisible(true)]
[ComDefaultInterface(typeof(ITestA2))]
public class TestA2 : TestA, ITestA2
{
    public bool DummyBool() { return true; }
}

.NET 备注

In COM interfaces can inherit from one another. However the .NET implementation that exposes the .NET interface to COM does not support inheritance. Therefore you must replicate any interface members in a base interface to the derived interface.

参见 COM Interop: Base class properties not exposed to COM