尝试在C#中构建一个可以从VB5 / 6引用和使用的COM组件

我试图看看我是否可以在C#(.NET 4)中构建一个COM组件,我可以从VB5程序(提示嘲讽性评论)中使用它来访问Web服务。 按照我在MSDN和CodeProject上找到的所有说明,如下所示:

  • 在C#中构建COM对象
  • 示例COM类(C#编程指南)

我写了以下内容:

[Guid("7A715F02-D349-45DC-B0AE-9925FD3B943C")] public interface ARCOM_Interface { [DispId(1)] string GetServiceResponse(); } [Guid("5130F041-619E-41F9-84B6-8332642228F6") , InterfaceType(ComInterfaceType.InterfaceIsIDispatch)] public interface ARCOM_Events { } [Guid("0A77754F-34CF-4E0E-AAC2-85FD686758E0") , ClassInterface(ClassInterfaceType.None) , ComSourceInterfaces(typeof(ARCOM_Events))] [ComVisible(true)] public class ARCOM_Class : ARCOM_Interface { public string GetServiceResponse() { string response = string.Empty; ARWebService.ARWebService svc = new ARWebService.ARWebService(); response = svc.PingMeBack(); return response; } } 

有问题的大会以强名称签署,输出已注册COM Interop。 构建之后,我已经将RegAsm应用于它并使用tlbexp.exe生成了一个类型库。

在VB6中,当我从Project属性中打开引用列表时,我可以在列表中找到程序集,我可以检查它。 我甚至可以在VB6代码中执行以下操作:

 Private Sub HitWebService() Dim arcom As ARCOMObject.ARCOM_Class arcom. <== Intellisense doesn't sense anything! End Sub 

Intellisense看到ARCOMObject和类,但ARCOM_Class本身内没有任何内容(除了通常的“GetType”,“Equals”和其他通用Object方法/属性)。 最具体地说,它似乎没有看到GetServiceResponse()方法,所以我无法调用它。

我要离开的是什么?

在我打电话给你的回复时,我看到你已经找到了想要得到你想要的东西的方法,但无论如何我会继续,因为它可能会告诉你一些你不知道的东西……

您已将ClassInterface(ClassInterfaceType.None)属性应用于该类。 这告诉COM互操作不要为类定义显式接口,因此您的客户端必须使用IDispatch(后期绑定)。 这意味着您的客户端必须具有该类实现的接口的先验知识。 也就是说,您(程序员)知道可用的方法,但IntelliSense等工具无法找到该信息。

只需继续并调用方法:

 Dim response As String response = arcom.GetServiceResponse 

好吧,我发现了一些意想不到的东西。

请注意,上面的代码包含装饰[ComVisible(true)]。 使组件对COM可见当然是必不可少的。 我认为这涵盖了它,但经过进一步搜索,我发现还有另一个地方可以标记它。 如果查看项目属性,则在“应用程序”选项卡中,您将找到“assembly信息…”按钮。 单击它,在对话框的底部,您将看到一个复选框“Make assembly COM-visible”。 我检查了一下,重新编译(并重新运行tlbexp和regasm),然后发现方法GetServiceResponse()是可见的。

我不知道为什么make ComVisible复选框在设置属性时不起作用。

编辑补充说:我想我知道这是怎么回事。 ComVisible(true)使类对COM可见,但对汇编不可见; 这就是为什么需要检查“Make assembly COM-visible”,因为GetServiceResponse方法似乎通过ARCOM_Interface获得COM可见性,除非程序集也是如此,否则它不会被标记为ComVisible。