使用tlbimp.exe
工具导入基本类型库始终为每个coclass
创建一个界面。例如,此IDL描述
interface IFoo : IUnknown
{
HRESULT DoSomething();
}
coclass Bar
{
[default] interface IFoo;
}
结果:
IFoo
,作为COM接口的表示,BarClass
,作为COM coclass和Bar
,使用CoClassAttribute
注释。 Bar
和IFoo
的GUID相等。关于此主题的MSDN个州:
此接口与coclass的默认接口具有相同的IID。通过此接口,客户端始终可以注册为事件接收器。
这是我在这个主题上唯一发现的东西。我知道,由于CoClassAttribute
,我可以使用该接口来创建实际类的实例。我也知道(实际上)我可以简单地使用BarClass
来创建一个新的类实例。我不明白的是,为什么导入过程会生成Bar
接口,即使coclass
没有定义事件源,也没有事件接收器可以连接到它。
在此示例中是否可以删除Bar
接口 1 ,还是存在其他风险,我还没有考虑过?
答案 0 :(得分:5)
你的名字错了,这无助于理解正在发生的事情。类型库中的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中实现。同样是一个单独的界面,在引擎盖下有一个用于订阅事件的复杂机制(IConnectionPoint等)。合成的BarClass使它们成为真正的.NET事件。