What are the CoClass interfaces in imported assemblies exactly for?

1k views Asked by At

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 the CoClassAttribute.

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.

1

There are 1 answers

1
Hans Passant On BEST ANSWER

You got the names wrong, that doesn't help understanding what's going on. The Bar coclass in the type library generates a Bar interface and a BarClass 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 synthesized Bar 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.