Importing a basic type library using the tlbimp.exe
tool allways creates an interface for each coclass
. For example this IDL-description
interface IFoo : IUnknown
{
HRESULT DoSomething();
}
coclass Bar
{
[default] interface IFoo;
}
results in:
- an interface
IFoo
as a representation of the COM interface, - a class
BarClass
as a representation of the COM coclass and - an interface
Bar
, annotated with theCoClassAttribute
.
Where the GUIDs of Bar
and IFoo
are equal. The MSDN states on this topic:
This interface has the same IID as the default interface for the coclass. With this interface, clients can always register as event sinks.
That's the only thing I found on this topic. I know that, due the CoClassAttribute
, I can use the interface to create instances of the actual class. I also know that (practically) I can simply use BarClass
to create a new instance of the class. What I don't understand is, why the import process generates the Bar
interface, even if the coclass
does not define an event source and thus no event sink can be connected to it.
Would it be possible to remove the Bar
interface 1 in this example or are there some other risks, I have not yet considered?
1 For example by disassembling the interop assembly.
You got the names wrong, that doesn't help understanding what's going on. The
Bar
coclass in the type library generates aBar
interface and aBarClass
class, there is no "FooBar".This is just extra glue that the type library auto-generates to make porting code easier. Particularly important for VB6 code, it took lots liberties with the COM object model. A VB6 program uses a coclass as though it is a real class with an implementation. No such thing exists in COM, the coclass is an opaque place-holder for the class, it is the interfaces that do all the work. VB6 never supported the notion of interfaces so directly modeling COM in the code wasn't possible.
The VB6 compiler itself generates a coclass from the Class keyword in the code and generates an interface that carries the actual methods and properties. That interface is hidden, it has the same name of the class but with a leading underscore. By convention, that causes object browsers to hide the interface. So your
Bar
coclass, when written in VB6, would generate a_Bar
interface.So a converted VB6 program would use
Bar
everywhere. This would not compile unless "Bar" was replaced by "IFoo". The synthesizedBar
interface comes to the rescue, avoiding the need for that.Still two problems left to solve, fixed by the synthetic
BarClass
type.New Bar()
will not compile since it is not legal to create an instance of an interface. The compiler solves that problem, it automatically substitutes "Bar" with "BarClass". Which is the actual role of the [CoClass] attribute, it provides the name for the class associated with the interface. And events are a problem, they are implemented in COM by a dispinterface. Again a separate interface with a convoluted mechanism under the hood that subscribes events (IConnectionPoint et al). The synthetic BarClass makes them true-blooded .NET events.