Introduction to Interoperability Between COM and .NET
The Component Object Model (COM) and .NET platform have vastly different type systems and mechanisms for object lifetime management, interface creation, and interface inheritance. For example, a Variant type in COM is a System.Object data type under .NET. To create an object, a COM client calls CoCreateInstance, whereas a .NET client can use keywords such as new or New that are built-in to a managed programming language. While COM does not support classical inheritance and a COM client manages an internal reference count provided by IUnknown to free a coclass, a .NET client relies on the runtime garbage collector provided by the .NET platform to free an object. Given such differences between COM and .NET, developing a managed client on a COM object model requires a mechanism that resolves these differences. The Runtime Callable Wrapper (RCW) is a mechanism that promotes transparent .NET to COM communication.
This topic gives a high-level description of how the RCW facilitates communication between COM and .NET. Note that even though this topic uses Microsoft Visual Studio to illustrate the RCW mechanism, you can use an interop assembly outside of Visual Studio to develop a managed client.
Facilitating Interoperability: the Interop Assembly and RCW
An interop assembly defines managed interfaces that map to a COM-based type library and that a managed client can interact with. To use an interop assembly in Visual Studio, first add a reference to the corresponding COM component. Visual Studio will automatically generate a local copy of the interop assembly. The interop assembly contains one namespace, under which there is a managed equivalent interface of each COM object in the COM object model. Figure 1 illustrates a managed client that wants to use a COM type library that defines coclass X. The managed client calls class X, which is the managed equivalent interface for coclass X, as defined in the interop assembly. At compile time, the managed project is compiled with information about class X from the interop assembly.
In general, as long as you set a reference to a type library, Visual Studio generates a copy of an interop assembly for that type library. Any number of interop assemblies can exist to describe the same COM type. However, a type library can have only one Primary Interop Assembly (PIA) which is the interop assembly published by the type library. Unlike other interop assemblies, the PIA is not generated every time you add a reference in Visual Studio. Instead, you install the PIA to the global assembly cache (GAC) just once on a computer. When you add a reference to the type library, Visual Studio automatically loads the PIA.
To program a managed solution for Outlook, you should use the Outlook PIA. To incorporate information from the Outlook PIA into a managed add-in, first you must install the Outlook 2007 PIA in the GAC. If you are using Visual Studio to create the managed project, after adding a reference to the Outlook 2007 type library, Visual Studio loads the PIA. In the object browser, under the namespace Microsoft.Office.Interop.Outlook, you can see managed interfaces that have names corresponding to objects in the Outlook object model. For example, the Account interface corresponds to the Account object in the Outlook object model. When you compile the managed project, this information is incorporated in your executable.
At run time, with the information provided by an interop assembly, the .NET runtime creates an RCW for each coclass the .NET client interacts with. Note that the runtime creates only one RCW for each coclass, regardless of how many interfaces the client has obtained from the coclass. The RCW is a .NET class type that wraps around the COM coclass. The RCW keeps track of the instances of the coclass and releases references to them only when the client no longer needs the RCW. This way, a .NET client does not have to manage the lifetime of an object the way an unmanaged client would under COM.
Figure 2 illustrates at runtime, an RCW intercepting an API call from a managed client, and using information from the interop assembly, transparently mapping the call to the corresponding API in the COM coclass. The following process describes how this happens:
The managed client calls method A' of class X' as defined in the interop assembly for a COM type library.
If an RCW does not yet exist for class X', the .NET run time uses information from the interop assembly and creates an RCW for class X'.
The RCW intercepts the call to method A', translates the arguments into corresponding COM types, and invokes method A of coclass X as defined in the COM type library.