Article source code: interopdotnet.zip
.NET Framework exposes COM objects through a proxy called Runtime-Callable Wrapper (RCW). Primary function of RCW is to marshal call between a managed client (.NET) and unmanaged COM object. Runtime maintains single RCW for each COM object.
The aim of this article is to create a demo project to show how to call a COM component from .NET client and to implement events raised by the COM component. Example provided here uses COM server and .NET client extending functionality of the COM server using delegation.
Step 1
Let's start by creating the COM component (DotNETInterOp.dll) in VB. The component consists of a single class "CEmp", that have properties (FirstName, LastName, DOB) and raises event (Senior).
After creating DotNETInterOp.dll register it by calling regsvr32 from command line
regsvr32 C:\testbeds\DotNETInterOP\DotNETInterOp.dll
CEmp Class of the DotNETInterOp component
Option Explicit
Public Event Senior()
Private mstrFirstName As String
Private mstrLastName As String
Private mdtDOB As Date
Public Property Get FirstName() As String
FirstName = mstrFirstName
End Property
Public Property Let FirstName(xstrFirstName As String)
mstrFirstName = xstrFirstName
End Property
Public Property Get LastName() As String
LastName = mstrLastName
End Property
Public Property Let LastName(xstrLastName As String)
mstrLastName = xstrLastName
End Property
Public Property Get DOB() As Date
DOB = mdtDOB
End Property
Public Property Let DOB(xdtDOB As Date)
mdtDOB = xdtDOB
If DateDiff("YYYY", mdtDOB, Now) > 60 Then
RaiseEvent Senior
End If
End Property
|
Step 2
To use the COM server we just created in .NET, Type Library of the component should be imported into Assembly containing metadata so that managed clients can create instances of the COM type and call its methods, just as if they were a .NET instance.
There are four ways to create an interop assembly
- Add reference to the type library using Visual Studio.NET
Open .NET project in Visual Studio.NET and add reference to the COM component using the Add Reference dialog box. This will automatically create interop assembly containing metadata.
- Type Library Importer
Use Type Library Importer (TlbImp.exe). TlbImp.exe is a command-line tool that converts COM type library to assembly containing metadata.
- TypeLibConverter Class
TypeLibConverter Class of the System.Runtime.InteropServices namespace provides methods to convert type library to assembly. This API can convert in-memory Type library and produces the same output as TlbImp.exe
- Custom Wrappers
You can create a duplicate definition of the class or interface in managed source code. You then compile the source code with compiler that targets the runtime to produce metadata in assembly. To define COM types manually, you must know exact descriptions of the coclasses and interfaces being defined and know the type library-to-assembly conversion rules. Writing custom wrapper is advanced technique that you seldom perform.
In our example we will use the TlbImp.exe to create metadata from the coclasses and interfaces definitions in our DotNETInterOp.dll Type library. From the command line run
tlbimp C:\testbeds\DotNetInterOP\DotNETInterOp.dll
/out:C:\.NET\TestBeds\VB\RCW\RCW\DotNETInterOp.dll
Step 3
Use the COM server, as it was a .NET component, add reference to the assembly created in the previous step and code against the assembly by creating CEmp object and delegation the calls to this object.
The .NET Client has two classes CEmp and CEmps, CEmp is a wrapper over our COM component's CEmp and exposes FirstName, LastName and IsSenior properties. The FirstName, LastName properties just delegate to the properties of COM's CEmp but IsSenior uses the event raised by the COM component to set its value. The CEmps class is a collection of CEmps and exposes methods to test our code.
VB.NET Client for the COM Component
Imports System.Collections
Public Class CEmps
Private Emps As ArrayList
Sub New()
Emps = New ArrayList()
Dim objEmp As CEmp
objEmp = New CEmp("John", "Doe", "01/01/1970")
Emps.Add(objEmp)
objEmp = New CEmp("Mike", "Edwards", "01/01/1941")
Emps.Add(objEmp)
objEmp = New CEmp("Debra", "Bunn", "01/01/1930")
Emps.Add(objEmp)
End Sub
Public Function Print() As String
Return Print(True) & Print(False)
End Function
Public Function Print(ByVal xblnSeniors As Boolean) As String
Dim intCount As Integer
Dim objEmp As CEmp
Dim strPrint As String
For intCount = 0 To Emps.Count - 1
objEmp = CType(Emps(intCount), CEmp)
If xblnSeniors = objEmp.IsSenior Then
strPrint = strPrint & Print(objEmp) & Chr(13)
End If
Next
Return strPrint
End Function
Private Function Print(ByVal xobjEmp As CEmp) As String
Dim strPrint As String
strPrint = xobjEmp.FirstName & Chr(9) & xobjEmp.LastName
Return strPrint
End Function
End Class
Imports System
Imports Microsoft.VisualBasic
Imports DotNETInterOp
Public Class CEmp
Private mobjEmp As DotNETInterOP.CEmp
Private mblnIsSenior As Boolean
Sub New(ByVal xstrFName As String, _
ByVal xstrLName As String, ByVal xdtDOB As Date)
mobjEmp = New DotNETInterOp.CEmp()
AddHandler mobjEmp.Senior, _
New DotNETInterOp.__CEmp_SeniorEventHandler( _
AddressOf Senior)
With mobjEmp
.FirstName = xstrFName
.LastName = xstrLName
.DOB = xdtDOB
End With
End Sub
Public ReadOnly Property FirstName()
Get
Return mobjEmp.FirstName
End Get
End Property
Public ReadOnly Property LastName()
Get
Return mobjEmp.LastName
End Get
End Property
Public ReadOnly Property IsSenior()
Get
IsSenior = mblnIsSenior
End Get
End Property
Private Sub Senior()
mblnIsSenior = True
End Sub
End Class
|
Related Articles
.NET Interoperability - Calling a .NET Component from a COM Component