7

使用该工具导入基本类型库tlbimp.exe总是会为每个coclass. 例如这个 IDL 描述

interface IFoo : IUnknown
{
    HRESULT DoSomething();
}

coclass Bar
{
    [default] interface IFoo;
}

结果是:

  • 一个接口IFoo作为 COM 接口的表示,
  • BarClass作为 COM coclass 的表示的类和
  • 一个接口Bar,用CoClassAttribute.

Bar和的 GUIDIFoo相等的地方。MSDN关于这个主题的状态:

此接口与 coclass 的默认接口具有相同的 IID。使用此接口,客户端始终可以注册为事件接收器。

这是我在这个主题上发现的唯一内容。我知道,由于CoClassAttribute,我可以使用接口来创建实际类的实例。我也知道(实际上)我可以简单地使用它BarClass来创建类的新实例。我不明白的是,为什么导入过程会生成Bar接口,即使coclass没有定义事件源,因此没有事件接收器可以连接到它。

是否可以删除此示例中的Bar接口1或是否还有其他风险,我尚未考虑?

1 例如通过拆卸互操作组件

4

1 回答 1

6

你把名字弄错了,这无助于理解发生了什么。Bar类型库中的coclass 生成一个Bar接口和一个BarClass类,没有“FooBar”。

这只是类型库自动生成的额外粘合剂,以使移植代码更容易。对于 VB6 代码尤其重要,它对 COM 对象模型有很大的自由度。VB6 程序使用 coclass 就好像它是具有实现的真实类一样。COM 中不存在这样的东西,coclass 是类的不透明占位符,它是完成所有工作的接口。VB6 从不支持接口的概念,因此无法在代码中直接对 COM 建模。

VB6 编译器本身从代码中的 Class 关键字生成一个 coclass,并生成一个承载实际方法和属性的接口。该接口是隐藏的,它与类具有相同的名称,但带有前导下划线。按照惯例,这会导致对象浏览器隐藏界面。因此Bar,当您用 VB6 编写时,您的 coclass 将生成一个_Bar接口。

因此,转换后的 VB6 程序可以Bar在任何地方使用。除非将“Bar”替换为“IFoo”,否则这不会编译。合成的Bar接口来拯救,避免需要。

还有两个问题需要解决,由合成BarClass类型解决。 New Bar()不会编译,因为创建接口的实例是不合法的。编译器解决了这个问题,它自动将“Bar”替换为“BarClass”。其中 [CoClass] 属性的实际作用是提供与接口关联的类的名称。并且事件是一个问题,它们是通过一个调度接口在 COM 中实现的。再次是一个单独的接口,其底层具有复杂的机制来订阅事件(IConnectionPoint 等)。合成 BarClass 使它们成为真正的 .NET 事件。

于 2014-01-03T16:27:25.520 回答