天天看點

interoperability between COM and .Net Component

cite from http://msdn2.microsoft.com/en-us/library/ms973800.aspx.

The Joy of Interoperability

Sometimes a revolution in programming forces you to abandon all that's come before. To take an extreme example, suppose you have been writing Visual Basic applications for years now. If you're like many developers, you will have built up a substantial inventory of code in that time. And if you've been following the recommendations from various language gurus, that code is componentized. That is, by using COM (Component Object Model)—formerly Microsoft ActiveX®—servers, you've broken your application into chunks of callable functionality. Of course, you're also likely to have a substantial investment in components, such as ActiveX controls, from other developers and other companies.

But what if you decide on the radical move of switching development to another operating system entirely? At that point, your entire investment in COM becomes worthless. You can't use any of your existing code, and you have to learn how to do everything on the new platform. Undoubtedly this would be a severe blow to your productivity.

Fortunately, switching from COM to Microsoft .NET involves no such radical loss of productivity. There are two key concepts that make it much easier to move from COM development to .NET development without any loss of code base or productivity:

  • .NET components can call COM components.
  • COM components can call .NET components.

This two-way interoperability is the key to moving from COM to .NET. As you learn the intricacies of .NET, you can continue to use COM components. There are a number of situations where this interoperability is useful:

  • You won't know everything about .NET instantly. It takes time to learn the .NET programming concepts and implementation, so you will probably need to continue critical development in COM.
  • Although Microsoft Visual Basic 6 code can be ported to .NET, the conversion isn't perfect. You may have components that can't be moved to .NET because of implementation or language quirks.
  • You can't write all the code for a large application immediately in a new system such as .NET. It makes much more sense to write components individually and test them one at a time, while still interoperating with your existing code.
  • You may be using third-party COM components for which you do not have source code.

In this document, you'll learn the details of calling COM servers from .NET clients. In a companion article, Calling a .NET Component from a COM Component, you'll learn about calling in the other direction, from COM clients to .NET servers.

Unmanaged Code and Runtime-Callable Wrappers

Code that operates within the Microsoft .NET Common Language Runtime (CLR) is called managed code. This code has access to all the services that the CLR brings to the table, such as cross-language integration, security and versioning support, and garbage collection. Code that does not operate within the CLR is called unmanaged code. All of your legacy COM components are, by definition, unmanaged code. Because COM was designed before the CLR existed, and COM code does not operate within the framework provided by the CLR, it can't use any of the CLR services.

The problem with mixing managed and unmanaged code in a single application is that the unmanaged code isn't recognized in the CLR environment. Managed code components not only depend on the CLR, they expect other components with which they interact to depend on the CLR.

The way out of this dilemma is to use a proxy. In general terms, a proxy is a piece of software that accepts commands from a component, modifies them, and forwards them to another component. The particular type of proxy used in calling unmanaged code from managed code is known as a Runtime-Callable Wrapper, or RCW. Figure 1 shows schematically how RCWs straddle the boundary between managed and unmanaged code. This figure includes a .NET program named NetUI.exe, two COM components named BackEnd.dll and Service.dll, and the necessary technology that connects them.

interoperability between COM and .Net Component

Figure 1. Calling unmanaged code with RCWs

Converting Metadata with TLBIMP

Of course, .NET is not the first to use metadata to describe public interfaces. In fact, COM type libraries also contain metadata describing the public interface to COM components. The job of an RCW is to convert this COM metadata to .NET metadata.

One tool for performing this conversion is called tlbimp (type library importer), and it is provided as part of the .NET Framework Software Developer Kit (SDK). Tlbimp reads the metadata from a COM type library and creates a matching CLR assembly for calling the COM component.

Note   If you build an ActiveX DLL or ActiveX EXE with Visual Basic, the type library is embedded within the DLL or EXE file.

Tlbmp is a command-line tool with a number of options for such things as signing the resulting assembly with a cryptographic key or resolving external references in the type library. (Type tlbimp /? at a command prompt to see all the options.) The most important option is /out, which lets you specify a name for the resulting .NET assembly. For example, to convert a Visual Basic ActiveX DLL named support.dll to a matching .NET assembly with the name NETsupport.dll, you could use this command line:

interoperability between COM and .Net Component

Copy Code

tlbimp support.dll /out:NETsupport.dll
           

Using COM Components Directly

As a Visual Basic .NET developer, you also have the option of using COM components directly. At least, that's what it looks like, although you're programmatically still using a RCW to get to objects in unmanaged code. If you're working within a Visual Basic .NET project, you can follow these steps to add a reference to a COM component:

  1. Click Project, and then click Add Reference.
  2. In the Add Reference dialog box, click the COM tab.
  3. Select the type library you wish to use from the list and click Select, or use the Browse button to locate a component that's not listed. The selected components will be added to the lower listview in the dialog box.
  4. Click OK to create RCWs for the selected type libraries in your Visual Basic .NET project.

When you do this, you'll find that Visual Basic .NET actually creates a DLL in your project's /Bin folder, with a name derived from the original COM component name. For example, if you reference BackEnd.dll version 2.0 in this manner, Visual Basic .NET will create the RCW in the file Interop.BackEnd_2_0.dll.

The major drawback to this shortcut method of using a COM component directly is that there's no opportunity to sign the resulting code. As a result, you cannot place the code in the Global Assembly Cache (GAC), which in turn makes it impossible to share the component among multiple .NET applications.

Choosing Between TLBIMP and Direct Reference

Although either method of using a COM component allows .NET code to call your COM component, there are some reasons to choose one over the other:

  • For a COM component that will only be used in a single Visual Basic .NET project, and which you wrote yourself, use direct reference rather than doing any extra work. This method is only suitable for a truly private component that does not need to be shared.
  • If a COM component is shared among multiple projects, use tlbimp so that you can sign the resulting assembly and place it in the Global Assembly Cache. Shared code must be signed. This method also allows you to create the RCW with a specific name in a specific location.
  • If you need to control advanced details of the created Assembly, such as its Namespace or version number, you must use tlbimp. The direct reference method gives you no control over these details.
  • If you did not write the COM component, neither one of these methods is acceptable. That's because you are not allowed to sign code written by another developer. What you need to do in that case is obtain a Primary Interop Assembly (PIA) from the original developer of the component. MSDN includes links to help you find PIAs for common components such as ActiveX controls.

繼續閱讀