Using .NET Components in COM

 
Chapter 17 - COM Interoperability
bySimon Robinsonet al.
Wrox Press 2002
  

Using .NET Components in COM

Just as you can use COM components and ActiveX controls in .NET code, so you can use .NET components in standard, unmanaged code, too. Only a few features of .NET assemblies are not accessible via COM, including parameterized constructors, static methods, and constant fields. Additionally, accessing overloaded .NET methods from COM requires a little work.

In this section, we shall look at how .NET components can be exposed to COM clients through a wrapper, analogous to the RCW, and discuss some of the requirements for classes that can be consumed from a COM client. Then, we have a .NET component example, and look at two utilities that facilitate COM clients binding to .NET components:

  • RegAsm.exe , used to register a .NET component with the COM runtime

  • TlbExp.exe , used to export type libraries for early-binding to .NET components

COM-Callable Wrappers

As we have the RCW for using COM components with .NET clients, so we have the corresponding notion of a COM Callable Wrapper, through which an unmanaged COM client can consume a .NET component. After all, a .NET object has no knowledge of COM, nor any real interest in COM-specific type information.

In order for a COM client to reference a .NET component, a COM-Callable Wrapper (CCW) needs to be generated for the component. This wrapper is used by COM clients as a proxy for the .NET component. When a COM client calls a .NET object, both the .NET object and a CCW are created. Note that only one CCW is created for each managed object, regardless of the number of COM clients that might be calling the object.

click to expand

A type library containing COM-specific information for the .NET component is generated by the TlbExp.exe tool (or RegAsm.exe with a /tlb: option), which we shall look at later, and this library can be used by unmanaged clients to bind to the components.

COM clients maintain reference counts on the CCW proxy, rather than on the actual .NET component. The CCW lives only as along as any COM clients have references on the object. The CCW dies when the COM client releases the last reference to it. When this happens, the CCW marks the managed .NET component for garbage collection. Analogous to the RCW, the CCW is responsible for marshaling the method call parameters that move back and forward between the COM client and the .NET component.

Requirements of .NET Components

To ensure that a COM client can use your .NET component, there are some requirements on your .NET classes:

  • Classes must be public, with a default public constructor

  • Since only public types are exported to the type library, consequently, only methods, properties, and so on, that are public will be visible to COM

Without a default public constructor, it may still be possible for a COM client to create the object by some other means. Furthermore, your classes should not be abstract and they should explicitly implement any interfaces.

The C# Factorial Component

As an example, consider the following code in a C# Class Library called CSharpFactorial . It simply accepts a number as an input argument and returns the factorial of that number, as our earlier C++ example did. We will make use of this component from a simple VBScript client later:

   using System;     namespace CSharpFactorial     {     public class Factorial     {         //THIS METHOD COMPUTES THE     //FACTORIAL FOR A NUMBER.     public int ComputeFactorial(int n)     {     int intFactorial=n;     for (int i=1;i<n;i++)     {     intFactorial*=i;     }     return intFactorial;     }     // A private method that will not be available to COM     private int DoubleNumber (int n)     {     return n*2;     }     }     }   

Note the private method DoubleNumber() .

Before we can use our component with a VBScript client, we have to install the assembly CSharpFactorial.dll into the global assembly cache. This is familiar to us from Chapter 8, so we will not spend time on it here.

Now we need to register the component with the RegAsm.exe tool:

RegAsm.exe

RegAsm (Register Assembly) is in charge of entering a .NET component's type information into the system Registry so that the COM runtime can access it. Once you've registered a .NET component with RegAsm , standard COM clients can bind to the component. The process of registering the component only has to be done one time. After it is registered, all COM clients can access it.

To finish off the task of registering our example CSharpFactorial DLL, we simply use RegAsm.exe thus:

  regasm CSharpFactorial.dll  

The VBScript COM Client

Now that the assembly has been registered with COM via RegAsm , we're free to bind to the .NET assembly through COM. For demonstration purposes, we'll be using VBScript. Simply type the following code into any text editor and save it as Factorial.vbs . Assuming that you have Windows Script Host installed, the file will run as a script when invoked. Note that VBScript employs late binding for COM components.

   Option Explicit     Dim objFactorial     Dim lngResult     Dim lngInputValue     Set objFactorial=CreateObject("CSharpFactorial.Factorial")     lngInputValue=InputBox("Number?")     lngResult=objFactorial.ComputeFactorial(CLng(lngInputValue))     Call MsgBox(lngResult)   

When you execute the VB script, it uses COM to instantiate the .NET object, calls a method on that object, and displays the value returned from the .NET object in a message box:

click to expand

As you probably know, VBScript uses late binding - that's why it was able to create our .NET object in the example here. Unfortunately, this approach does not solve any of the aforementioned dangers associated with late binding.

Early Binding to .NET Components

If a COM client wants to early-bind to a .NET component, we have two options. Firstly, we can tell RegAsm that we want to generate a type library using the /tlb switch:

   RegAsm CSharpFactorial.dll /tlb:CSharpFactorial.tlb   
click to expand

Alternatively, we can use the Type Library Exporter program, TlbExp.exe .

TlbExp.exe

The Type Library Exporter, TlbExp.exe , inspects an assembly and exports all its public types into a corresponding type library containing COM-specific type information; a .tlb file that can be made available to unmanaged COM clients.

Once TlbExp (or RegAsm with the /tlb: option) has created a type library file for a .NET component, non-.NET development languages such as VB 6 can reference it, using it to effectively achieve early binding to the .NET components:

click to expand

Let's use TlbExp on our CSharpFactorial example, and have a look at the resulting type library with the OleView utility:

click to expand

We can see our ComputeFactorial method, but no DoubleNumber method; this is expected, since DoubleNumber was private.

  


Professional C#. 2nd Edition
Performance Consulting: A Practical Guide for HR and Learning Professionals
ISBN: 1576754359
EAN: 2147483647
Year: 2002
Pages: 244

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