导入程序集中的CoClass接口到底有什么作用?

7

使用tlbimp.exe工具导入基本类型库总是为每个coclass创建一个接口。例如,这个IDL描述:

interface IFoo : IUnknown
{
    HRESULT DoSomething();
}

coclass Bar
{
    [default] interface IFoo;
}

结果是:
  • 接口IFoo表示COM接口,
  • BarClass表示COM coclass,和
  • 一个用CoClassAttribute注释的接口Bar

BarIFoo的GUID相等。在这个主题上,MSDN指出:

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

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

在这个例子中是否可能删除Bar接口1,或者是否存在我尚未考虑的其他风险?

1 例如通过反汇编互操作程序集

1个回答

6
您将名称弄错了,这并没有帮助理解正在发生的事情。类型库中的Bar coclass生成了一个Bar接口和一个BarClass类,而没有“FooBar”。
这只是类型库自动生成的额外粘合剂,使移植代码变得更容易。这对于VB6代码尤为重要,它在COM对象模型方面采取了很多自由。VB6程序将coclass用作实现的真实类。在COM中不存在这样的东西,coclass是类的不透明占位符,起作用的是接口。VB6从未支持过接口的概念,因此无法直接对COM进行建模。
VB6编译器本身从代码中的Class关键字生成一个coclass,并生成一个携带实际方法和属性的接口。该接口是隐藏的,它具有与类相同的名称,但前面有下划线。按照惯例,这会导致对象浏览器隐藏接口。因此,当您在VB6中编写Bar coclass时,将生成一个_Bar接口。
因此,转换后的VB6程序将在各处使用Bar。如果不将“Bar”替换为“IFoo”,则无法编译。合成的Bar接口就派上用场了,避免了这种需要。
仍然有两个问题需要解决,由合成的BarClass类型解决。由于创建接口的实例是不合法的,因此New Bar()无法编译。编译器解决了这个问题,它自动使用“BarClass”替换“Bar”。这就是[CoClass]属性的实际作用,它提供与接口相关联的类的名称。事件也是一个问题,它们在COM中通过dispinterface实现。再一次,这是一个具有复杂机制的单独接口,用于订阅事件(如IConnectionPoint等)。合成的BarClass将它们变为真正的.NET事件。

我已经修正了问题中的名称。感谢您的回答!由于我不是在移植VB6应用程序,而且我上面的示例coclass没有定义事件,所以我认为您的答案意味着我可以删除接口,并回答了我最后一句话的问题。如果我错了,请纠正我!否则 - 感谢您的努力! :) - Carsten

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接