Exposing .NET Events in COM

team lib

.NET uses a delegate-based event model, while COM uses connection points. The discussion that follows assumes you are familiar with the way in which COM implements events using connection points, as well as the way in which .NET implements events using delegates. A brief overview of the COM mechanism was presented in the Responding to COM Events section in Chapter 3, but if you need more information, consult Inside COM , by Dale Rogerson (Microsoft Press, 1997).

For more information on delegates and events, consult a book appropriate to your .NET programming language, such as Inside C# , by Tom Archer, or Programming Microsoft Visual Basic .NET , by Francesco Balena, both published by Microsoft Press.

As explained in Chapter 3 in the section Responding to COM Events, these mechanisms are logically similar and intended to fulfill the same requirements but they use completely different implementations . If a .NET component is going to act as a source of events that COM clients can consume , the .NET component needs to implement some additional code that lets it simulate the COM connection-point mechanism.

Using Explicit Source Interfaces

A typical .NET class defines events using delegates and events. For example, a class representing a bank account could define an event that is called whenever the interest rate changes:

 //VisualC#example publicclassBank { publiceventRateChangeHandlerRateChange; ... }; 

.NET events defined in this way cannot easily be exposed to COM. The problem is that the event definition within the class will be exposed as part of the class interface, and it will be implemented as a pair of methods with add and remove prefixes:

 [id(0x6002004)]HRESULTadd_RateChange([in] _RateChangeHandler*value); [id(0x6002005)]HRESULTremove_RateChange([in] _RateChangeHandler*value); 

While this mimics the way that .NET clients hook event handlers to event sources, a COM client has no way to create a suitable RateChangeHandler object and pass it as an argument, given that RateChangeHandler needs to be a managed type.

The solution is to define an explicit event-source interface. This interface can then be linked to a class using the ComSourceInterfaces attribute, and the type library exporter will use it to implement COM connection-point access to the exported .NET object. Heres the sequence of events you need to follow:

  1. Create a source interface that defines the events to be exposed to COM clients.

  2. Use the ComSourceInterfaces attribute to tell the type library exporter that this interface is a source interface for an exported class.

  3. Build the assembly.

  4. Generate a type library using TlbExp.exe or an equivalent method.

  5. Use the type library with COM client code.


    As youll see in the example that follows, implementing a source interface doesnt preclude implementing .NET events on the same class. This means COM and .NET clients can both use events on the same .NET class.

The example in Listing 4-5 defines a class that represents a bank account, which exposes a single event that is fired when the interest rate on the account changes. You can find this sample in the Chapter04\Account folder of the books companion content.

Listing 4-5: Account.cs
start example
 usingSystem; usingSystem.Runtime.InteropServices; namespaceBank { //InterfacetoallowCOMclientstouseevents. //Defineitasapuredispatchinterface [ Guid("ef81a831-fa49-4ede-b70b-08f2e9d602b2"), InterfaceType(ComInterfaceType.InterfaceIsIDispatch) ] publicinterfaceIAccountEvents{ voidNewRate(doubleval); } //Delegateforratechangeevent publicdelegatevoidRateDelegate(doubleval); //ExporttheAccountclass,exposingIAccountEvents //asasourceinterface [ComSourceInterfaces(typeof(IAccountEvents))] publicclassAccount{ privatestaticdoubleinterestRate=0; //Definetheevent publiceventRateDelegateNewRate; publicAccount(){ } publicdoubleRate{ get{ returninterestRate; } } //Firetheevent publicvoidSetRate(doubled){ NewRate(d); } } } 
end example

The IAccountEvents interface defines the source interface for the Account class. It is exposed as a dispinterface as are most source interfacesand defines one method. The Account class defines a single event, based on the delegate RateDelegate , which can be used by .NET clients. The source interface is attached to the Account class using the ComSourceInterfaces attribute, which takes as its parameter a Type object representing the source interface. The SetRate method will fire the method when it is called.

Consuming Events in Visual Basic 6

Its simple to consume .NET events in COM-based code. As an example, here is how you could use the Account component in Visual Basic 6.

Create a project, and then use the References item on the Project menu to bring up the References dialog, as shown in Figure 4-4. If the Account class has been registered correctly, youll see an entry for it in the list. Check this entry before pressing OK.

click to expand
Figure 4-4: A correctly registered class will appear in the References dialog box.

This will add a reference to the class to the project. You can check what has been added by using the F2 key (or the Object Browser item on the View menu) to bring up the Object Browser window, as shown in Figure 4-5. You can see that the class exposes one event, shown by the lightning symbol:

click to expand
Figure 4-5: The Object Browser shows added classes and their related events.

You can test the Account component with some very simple code:

 DimWithEventsaccAsAccount.Account PrivateSubacc_NewRate(ByValvalAsDouble) MsgBox "Newaccountrateis " &val EndSub PrivateSubForm_Load() OnErrorGoToerrLab Setacc=NewAccount.Account acc.SetRate(5#) ExitSub errLab: MsgBox "Error:" &Err.Description EndSub 

The first line creates an Account object that is going to act as a source of events. The acc_NewRate function is a handler that will be called when the event is fired, and this is done in the Form_Load function once the object has been created. If you build and run the code, youll find the message box is displayed as the form is loading at the start of the program.

team lib

COM Programming with Microsoft .NET
COM Programming with Microsoft .NET
ISBN: 0735618755
EAN: 2147483647
Year: 2006
Pages: 140

Similar book on Amazon

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net