SUMMARY
This step-by-step article describes how to declare and
establish a COM event sink by using sink objects in Microsoft Visual Basic
.NET or in Microsoft Visual Basic 2005. The sample that appears in this article creates one sink object that
implements all the events that are exposed by the COM server. The COM server
uses return values from multiple events for later computations.
This
article also describes the problems that may occur when you use a delegate
model where the COM server cannot use return values from multiple
events.
back to the
topMORE INFORMATION
Note This article assumes that
MySrv is a user-defined COM server that is registered and exists on the
system. The COM server exposes two events,
Initialize and
CanShutdown. The COM server uses these events as follows:
- The COM server fires the Initialize event, and then stores the value in a variable.
- The COM server fires the CanShutDown event, and then stores the value in a variable.
"Event source" refers to the COM server and "event sink" refers
to the Microsoft .NET client throughout this article. For more information,
visit the following Microsoft Web site:
Microsoft .NET client consumes COM events by using the following:
- A classic COM connection point model.
- A Microsoft .NET delegate event model.
back to the
topClassic COM Connection Point Model
You can connect to a COM server by using the COM connection point
interfaces from managed code. All COM event classes provide the
IConnectionPointContainer interface. When you have the
IConnectionPointContainer interface, you must find the specific connection point of the
event interface that you want to subscribe to.
To use the classic COM
connection point model, follow these steps:
- In Microsoft Visual Studio .NET or in Microsoft Visual Studio 2005, click
File, and then click New Project.
- For Project Type, click Visual
Basic. For Template, click Console
Application.
- Name your project SampleClient, and
then click OK.
- In Solution Explorer, right-click
Reference, and then click Add Reference to
create a reference to MyAtlSrv.
- Click the COM tab, and then click the
MySrv COM object.
- Click OK.
- In Solution Explorer, right-click
SampleClient, and then click Add Class to
create the class for handling events.
- Type MyEventsSink.vb in the text
box, click the Class template, and then click
Open.
- To establish a COM event sink, use the following sample
code to modify the existing MyEventsSink class:
Imports MySrvLib
Public Class MyEventsSink
Implements _IMySrvEvents
Public Function CanShutdown() as Boolean Implements _IMySrvEvents.CanShutdown
Console.WriteLine("CanShutdown interface method")
Return True
End Sub
Public Function Initialize() as Boolean Implements _IMySrvEvents.Initialize
Console.WriteLine("Initialize interface method")
Return True
End Sub
End Class
- In the Main method of Module1.vb, use the FindConnectionPoint method to obtain the IConnectionPoint interface. To subscribe to the event, use the Advise method by using the following code:
Imports MySrvLib
Imports System.Runtime.InteropServices
Module Module1
Sub Main()
Dim cookie As Integer
Dim mySink As MyEventsSink = New MyEventsSink()
Dim myServerClass As MySrvClass = New MySrvClass()
Dim icpc As UCOMIConnectionPointContainer = CType(myServerClass, UCOMIConnectionPointContainer)
Dim icp As UCOMIConnectionPoint
Dim IID_IMyEvents As Guid = GetType(_IMySrvEvents).GUID
icpc.FindConnectionPoint(IID_IMyEvents, icp)
icp.Advise(mySink, cookie)
'Call to server function causes events to be raised.
myServerClass.SetParameter()
icp.Unadvise(cookie)
End Sub
End Module
back to the
topMicrosoft .NET Delegate Event Model
In the delegate event model, each time that an event handler is
registered, a COM sink object is created. To use the delegate model for
implementing the sink for
MySrv server, you can implement two delegates. In the following pseudo
code, two event handlers are registered. Therefore, two COM sink objects are
created:
Imports MySrvLib
Public WithEvents mySvrc As New MySrvClass()
...
Public Function re_Initialize() As Boolean Handles mySvrc.Initialize
Console.WriteLine("Initialize delegate")
Return True
End Function
Public Function re_CanShutdown() As Boolean Handles mySvrc.CanShutdown
Console.WriteLine("CanShutdown delegate")
Return True
End Function
Sub Main
mySvrc.SetParameter()
End Sub
...
This client pseudo code implements the two delegates as two complete
IMyEvents sinks:
- The first delegate sink implements the Initialize event by calling the re_Initialize delegate. The first event sink also provides default
implementation for the CanShutdown event, and then returns false as a default value.
- The second delegate sink implements the CanShutdown event by calling the re_CanShutdown delegate. The second event sink also provides default
implementation for the Initialize event, and then returns false as a default value.
back to the
topProblems in the .NET Delegate Event Model with Return Values
The following problems occur:
- The COM server fires the Initialize event for the first event sink, and then returns true from the re_Initialize delegate. Also, the COM server fires the CanShutdown event for the first event sink, and then always returns a default
value of false. However, the expected behavior of the CanShutdown event is to return a value of true.
- The COM server fires the Initialize event for the second event sink, and then always returns a
default value of false. Also, the COM server fires the CanShutdown event for the second sink, and then returns true. However, the expected behavior of the Initialize event is to return a value of true.
These problems occur when you use the return values from events
because the event source cannot distinguish between the default return value
and the actual return value.
The delegate event model with COM event
interfaces also introduces
overheads. For example, if you have nine methods in an event interface:
- To handle all nine methods in the interface, you create
nine delegates.
- These delegates generate nine event sinks.
- If the COM server fires one event method, the .NET
Framework formulates nine calls to the default generated methods.
However:
- To handle three of the nine methods in the event interface,
you create three delegates.
- These delegates generate three event sinks.
- If the COM server fires one event method, the .NET
Framework formulates three calls to the default generated methods.
This behavior may not be acceptable.
To work around
this behavior, create a .NET COM client by using the classic COM connection
point model, as described in the "More Information" section of this article.
back to the top