By Tim Landgrave
One of the key design decisions that Microsoft made during the development of the .NET Framework and the common language runtime (CLR) was to support its legacy technologies, including COM components and COM+ packages (which I’ll refer to collectively as COM). The developers in most large companies with which I work are taken aback when I refer to COM as a legacy technology—after all, they still work primarily with COM tools such as VB6. And to be totally accurate, much of the .NET Framework in the current 1.x releases doesn’t implement services in managed code, but relies on existing COM underpinnings. For example, the entire EnterpriseServices namespace wraps the unmanaged COM+ infrastructure exposed by the underlying Windows 2000 operating system.
But as .NET architects begin charting new applications and application scenarios, the move toward next generation architectures (e.g., Web services) means that more and more applications will be pure .NET applications and will need only to interoperate with existing COM assets until they can ultimately replace them. Making this interoperability seamless in the development and deployment of new .NET applications should be a priority for application designers. Let’s look at some of the key considerations.
When a running .NET application makes a call in to a COM object, the CLR generates a proxy between the managed .NET code and the unmanaged COM code called a runtime callable wrapper (RCW). The CLR uses an interop assembly as the blueprint from which it generates the RCW. Interop assemblies define only the types in existing COM components and have no implementation code. The resulting RCW allows managed code to bind to the types in the COM component at compile time and gives information to the CLR about how the types should be marshaled at runtime.
Since .NET applications require access to the interop assemblies to allow the CLR to generate the appropriate RCW, you must make sure the assemblies are available to your program during development and after deployment. Of course, any COM assets used by the .NET application must still be registered on the computer (components) or properly installed in the COM+ catalog (i.e., COM+ packages).
Using COM assets during development
Visual Studio .NET automatically creates the required interop assembly during development of .NET applications. When you add a reference to an existing COM asset, VS.NET creates an interop assembly that allows you to call the asset. But VS.NET uses what is called an alternative interop assembly rather than a primary interop assembly. This is important because the primary interop assembly has the official and signed definitions of the types defined in the type library, while the alternate interop assembly has unsigned versions of the types. Moreover, the CLR will generate a type mismatch exception if two applications pass a COM object between them, where one RCW is based on the primary and the other RCW is based on an alternative interop assembly. To be safe, you should always use primary interop assemblies during development.
To do this, you should either use the primary interop assembly provided by the component publisher (in the case of third-party components), or generate your own primary interop assemblies for your internally developed COM objects. You create interop assemblies using Type Lib Importer (Tlbimp.exe), which converts COM method signatures into managed signatures. To make the interop assembly a primary interop assembly, you must specify the /primary switch and sign the assembly. Once created, register the component and the primary interop assembly on the developer systems using Regasm, and place the primary interop assembly into the global assembly cache on the development computer. This allows you to use the COM component in any application you develop. More importantly, when you set a reference to the COM component, VS.NET will detect the presence of the primary interop assembly and use it instead of creating an alternative.
Deploying COM assets
If you configure the development environment properly, the deployment of .NET applications that use .NET assets is simple. The main difference is that the primary interop assembly doesn’t have to be registered on the deployment system. The reason for the registration on the development computer is to inform VS.NET that a primary interop assembly already exists.
On the deployment system, you simply place the primary interop assembly in the Global Assembly Cache (GAC) or in a private application directory with the rest of the application code. If the COM component is to be used by multiple applications on the same system, you should place the primary interop assembly in the GAC to make future updates easier.