Implementing Interface Events 
Author Message
 Implementing Interface Events

Quote:

> Does anyone know if you can implement an interface event in VB.

[Long article - and somewhat {*filter*}, above intermediate level]

Nice to see that I'm not alone in this case wanting a solution
to this problem. Me and a collegue have been pondering about this
for some time now.

Implementing interfaces using the Implements keyword is very useful.
The troublesome part is that events are not considered being part
of the interface. I know the reason for this, but it is anyway
akward since the events semantically are part of the interface
most of the time.

There are workarounds to this problem, one being to create an
event proxy object and raise the events through that object. That
has the drawback that the listening object has to declare and set
two references. One for the polymorphic object and one for the
event proxy. It allso hogs memory.

What I would like to see in VB is an 'Implements WithEvents'-keyword.
That is, that the implementing class implements not only the default
interface of the implemented class, but allso the default source
interface and a connection point implementation to go with it.

This should be able to be done since events seem to be invoked
using IDispatch in VB. I suspect this is so since the IDispatch
implementation seems to be different in a class with a source
interface and one with no events. The source interface implementation
has at least two more variables. Well, this is just plain guessing...

The sinks allso seem to call the listeners using IDispatch. This
is allso just a guess.

I would very much like to know if this is true since my knowledge
on this matter comes from memory dumps of objects and just thinking
about the consequences about VB generating sinks 'on the fly' for
each source interface. I feel like a novice here.

What I have been thinking about is a hideous hack to fool VB in
this case. First a little something about the problem:

First create a vb class containing the events you want to
share in your polymorphic classes, lets call it IFooEvents.

'IFooEvents class
Event FooUpdated()      ' Default source interface of IFooEvents
Public Sub Bar()        ' Default interface of IFooEvents
End Sub

Now, write a concrete class CFooListener. Declare a private variable
m_foo with the WithEvents keyword.

'CFooListener
Private WithEvents m_foo As IFooEvents

When this variable is set VB will, I suppose, create an event sink
for the IID of __IFooEvents (the default source interface of IFooEvents).
Then hook up as a listener calling the Advice method of the IConnectionPoint
interface of the CConnectionPoint object of the referenced IFooEvents
object.

The problem with this is that this can not be done since I can
not create a concrete class implementing the *source* interface
of IFooEvents. If I assign an object implementing IFooEvents the
source interface will not be implemented and Advice will fail
since the concrete class has its own (or no) default source
interface with another IID (The compiler might even optimize
this away).

Now for the hack, :-).

Compile the IFooEvents interface and steal the IID of the
default source interface, __IFooEvents, of the coclass IFooEvents.
This can be done using the OLE-COM viewer (The dll containing the
interface will need binary compatibility from now on to keep its
IID).

Now write a concrete class CFooRaiser.
'CFooRaiser
Event Update()
Implements IFooRaiser

This class will have its own source interface with a different
IID, BUT it will (pray to god) be binary compatible with __IFooEvents
apart from having a different IID.

What I would like to do is exchange the IID of the connection point
for the concrete IFooRaiser to the IID of __IFooEvents. This can be
done by using RtlCopyMemory if I know what pointers to dereference
and what offsets to use. If it works the conneciton point will allow
sinks for __IFooEvents to connect using the Advice method.

To know if this is even possible I need to know some things about the
intrinsics of VB:s implementation of events, namely these (and probably
many more, feel free to add your own questions and answers):

1) VB objects can only implement a single source interface. That to me
seems like the object _itself_ could implement IConnectionPoint
since multiple source interfaces need not be considered. Is this so?

2) Are events in VB raised using an implementation of IDispatch?

3) Are all VB sinks alike?

4) Will the compiler find out that I am assigning a CFooRaiser
to an IFooEvents interface pointer and skip the Sink-Advice stuff
since the CFooRaiser does not implement the __IFooEvents source
interface?

5) If the answer to Q4 is yes, could I fool the compiler by first
assigning a dummy instance of IFooEvents and then swap the object
pointer using ObjPtr and RtlCopyMemory?

6) How much does the VB sink know about the source interface
and its methods? Does it invoke the event callbacks to the CFooListener
instance using IDispatch? It should only have to provide the raising
method with the IDispatch interface of the CFooListener so the
raiser can call the sinking method 'directly', or?

7) Can I somehow guarantee that the source interfaces of CFooEvents
and CFooRaiser are binary compatible, apart from the IID?

8) Is this one of the reasons that VB still does not have inheritance?
I guess you MS guys and galls allready know that we miss it a lot out
here in the trenches...

9) And finally, the big question:
Am I totally mad and should be sent to an assylum immediatelly for
even considering this? ;-)

I would be very happy to hear any thoughts on this.

--
Mathias Holmgren                Entra Capital Solutions
+46 70 979 08 83                 http://www.*-*-*.com/



Sun, 11 Mar 2001 03:00:00 GMT  
 Implementing Interface Events
[Bugfix]

Quote:

> 'IFooEvents class
> Event FooUpdated()      ' Default source interface of IFooEvents

[snip]

Quote:
> Now write a concrete class CFooRaiser.
> 'CFooRaiser
> Event Update()

> This class will have its own source interface with a different
> IID, BUT it will (pray to god) be binary compatible with __IFooEvents
> apart from having a different IID.

Of course the Event must have the same name. Sorry, I blame
Mr Cut & Paste... Correct CFooRaiser below:

'CFooRaiser
Event FooUpdated()

If it has another name it can not be lowered by CFooListener
since it expects another name.

--
Mathias Holmgren                Entra Capital Solutions
+46 70 979 08 83                http://www.ecs.se/



Mon, 12 Mar 2001 03:00:00 GMT  
 Implementing Interface Events
Mathias -

    I am encourages by your comments, mostly because you have the same
complaint.  I also suspect that a hack of the nature you suggest may be the
only alternative, I will have to spend some time understanding your
suggestion as I am not as conversant in COM as yourself.  I eagerly await
any other suggestions or findings by yourself.

    - Ken

Quote:

>[Bugfix]


>> 'IFooEvents class
>> Event FooUpdated()      ' Default source interface of IFooEvents

>[snip]

>> Now write a concrete class CFooRaiser.
>> 'CFooRaiser
>> Event Update()

>> This class will have its own source interface with a different
>> IID, BUT it will (pray to god) be binary compatible with __IFooEvents
>> apart from having a different IID.

>Of course the Event must have the same name. Sorry, I blame
>Mr Cut & Paste... Correct CFooRaiser below:

>'CFooRaiser
>Event FooUpdated()

>If it has another name it can not be lowered by CFooListener
>since it expects another name.

>--
>Mathias Holmgren Entra Capital Solutions
>+46 70 979 08 83 http://www.ecs.se/



Fri, 16 Mar 2001 03:00:00 GMT  
 
 [ 3 post ] 

 Relevant Pages 

1. Implementing Interface Events...

2. How to implement event of an interface?

3. Implementing COM Interfaces that have events

4. Implement Interface and Events

5. Implement Interface and Events

6. Implement Interface that has events

7. IMPLEMENTING AN INTERFACE MADE FROM ANOTHER INTERFACE

8. Implementing an interface made from another interface

9. IMPLEMENTING AN INTERFACE MADE FROM ANOTHER INTERFACE

10. Implementing an interface made from another interface

11. Major bug with Interface Events and Shared Events

12. Implementing IUnknown interface in Access 2000 class

 

 
Powered by phpBB® Forum Software