views:

309

answers:

2

I want to expose a .NET class to COM. That's fairly easy:

  • I create an interface in where I define the members of that class that should be ComVisible
  • I define the DispId's of those members myself
  • I define that the interface should be ComVisible
  • I assign a Guid to that interface
  • I create a class which implements that interface

No big deal. This all works. But, now my question is: I have a few events in that class, that I want to expose to COM as well.
This should be no big deal either, but, when I look at some examples (f.i. code generated by MS' ComInterop tool), I see that the events are declared in a separate interface. That is: the class that should be ComVisible, implements 2 interfaces:

  • one interface which defines the regular methods and properties that should be ComVisible
  • another interface that defines the events that should be ComVisible.

Now, my question is: why is that ? What is the reason for this ?

Why are the ComVisible events defined in another interface, and why are they just not defined in the interface that contains the methods and properties that should be comvisible ?

What is the reasoning behind this ?

A: 

Events have always been defined on a separate interface. This is not unique to COM interfaces implemented by .NET, but all COM interfaces. The way I see it, an interface represents a collection of methods and properties, but methods on an event interface are not invoked like either of those. They are invoked by the server instead of the client, which doesn't match the behavior of normal methods. So by implementing these methods on a separate interface, you can separate the functions that can be invoked by the server from the methods that can be invoked by the client. The client should not be able to invoke event methods. It should be required to implement the interface on an object which the server can invoke. Likewise, the client should not be implementing interfaces that are already implemented in the server. It should be calling the existing implementation of those interfaces implemented in the server. The simplest way to handle this is to have one interface provided for the client to implement for event handling, and another implemented by the server that the client can call for already-implemented functions.

BlueMonkMN
+2  A: 

This is due to the way that COM events work. COM doesn't have any idea what a delegate is, and so its events are implemented using a callback interface. The object which wishes to receive events implements the events interface, passes it to the sender (your code), and the sender calls methods on it. The event interface is thus separate because you don't want someone interested in your events to have to implement the rest of your interface.

Behinds the scenes, event interfaces are managed using "connection points" which allow recipients to connect their callback interfaces to the sender. This implementation requires an assortment of COM interfaces (IConnectionPoint, IConnectionPointContainer, IEnumConnectionPoints, IEnumConnections) and some tedious housekeeping. If you're implementing COM events in e.g. native C++, you have to care about these interfaces. Fortunately as a .NET programmer you don't have to implement them, since .NET will do it for you.

El Zorko
Ok, I can understand what you're saying, but, why are the events not really visible when I do not define them in another interface via com ?Does it have something to do with the ComInterfaceType attribute ?
Frederik Gheysels
It's more to do with the ComSourceInterfaces attribute. Even though .NET can turn .NET events into COM events, it still requires you to arrange your code in such a way that it's clear how to sort things out on the COM side. The ComSourceInterfaces attribute instructs .NET that the class it's bound to can send events out using the given interface.
El Zorko