首页 - 图片 - 汽车 - 百科 - 旅游 - 美食 - 英语 - IT资讯 - 留学 - 移民 - 电影 - 下载 - 站点地图

您的位置: 易飞网 >> 资讯 >> VB.NET学习资料 >> C#|VB.Net技术文章 >> 查看资讯

COM和.NET的互用性

.NET平台是来自早期COM的一个主要技术转换,COM已经统治微软世界好多年了。尽管现在可以使用.NET进行新的开发,但是仍然需要使用一些现有的以COM组件形式存在的功能。在本文中,我会谈到一些COM和.NET互用的技术。

COM到.NET:技术的转变
<A HREF="http://ad.cn.doubleclick.net/click%3Bh=v2|3126|3|0|%2a|i%3B8140798%3B0-0%3B0%3B9118921%3B4252-1|1%3B5279172|5297068|1%3B%3B%7Efdr%3D8146806%3B0-0%3B0%3B6694713%3B31-1|1%3B5284115|5302011|1%3B%3B%3fhttp%3A%2F%2Fwww.intel.com/network/connectivity/sc/" TARGET="_blank"><IMG SRC="http://www.eeffee.com/attachments/2007/07/15/1_200707150832491.gif" WIDTH="336" HEIGHT="280" ALT="Click here..." BORDER="0">

尽管COM组件和.NET组件共享相同的.dll扩展名,但是它们在本质上并不相同。.NET组件并不需要把和它相关的信息保存在注册表里,但是它会把类型信息以元数据的形式保存下来。这个元数据是放在组件自身里的。更进一步说,.NET组件不是基于IUnknown接口的,而所有的COM对象都会公开这个接口。

以COM形式存在的代码被叫做不可管理代码(unmanaged code),因为这个代码的执行不由通用语言运行库(CLR)管理。使用.NET框架编写的代码可以由CLR管理,所以被叫做可管理代码(managed code)。

重新编写.NET里的每一段代码是不切实际的,因为很多功能是以COM的形式存在的。而且当前以COM形式存在的代码要比.NET的更多,因为.NET是一个相对较新的平台。正是由于这个原因,要求COM和.NET互用性的呼声正在增多。.NET框架里已经有一个专门的命名空间用于这个目的:System.Runtime.InteropServices命名空间提供了一些能够用于从.NET访问COM的类。下面,我们将通过从.NET调用COM对象开始——这通常是个必需的行为。

从.NET里调用COM对象
COM对象里的代码并不由CLR执行。把COM对象向.NET公开的机制如下:COM对象在包装函数类内部被封装,这会把COM对象作为.NET组件向CLR公开。这个包装函数就是运行库可调用包装函数(RCW)。A说明了这个处理过程。

图A

运行库可调用包装函数(RCW)



这个包装函数类扮演着不可管理和可管理代码之间桥梁的角色,而且所有的操作都要通过这个类。理论讲够了;让我们看看怎么做到这一点。生成RCW的整个处理过程都是由Visual Studio.NET自动处理的。

使用Visual Studio.NET实现互用性
让我们假设我么要在自己的应用程序里使用微软的Excel。访问项目菜单里的参照,并从COM选项卡里选择微软Excel对象库,就可以实现这个目的,见B

图B

选择微软Excel对象库


<A HREF="http://ad.cn.doubleclick.net/click%3Bh=v2|3126|3|0|%2a|i%3B8140798%3B0-0%3B0%3B9118921%3B4252-1|1%3B5279172|5297068|1%3B%3B%7Efdr%3D8146806%3B0-0%3B0%3B6694713%3B31-1|1%3B5284115|5302011|1%3B%3B%3fhttp%3A%2F%2Fwww.intel.com/network/connectivity/sc/" TARGET="_blank"><IMG SRC="http://www.eeffee.com/attachments/2007/07/15/1_200707150832491.gif" WIDTH="336" HEIGHT="280" ALT="Click here..." BORDER="0">

一旦我们这样做了,VisualStudio.NET就会自动生成一个RCW。随后根据命名习惯,它会被命名为Interop.COMObject.dll。在本文中,这个RCW被叫做Interop.Excel.dll,它会被.NET的应用程序参照;我们还能够在代码里实例化和使用Excel对象。任何由你自己创建的自定义COM组件也是这样的。唯一需要的条件就是这个COM组件需要进行注册。

你还可以使用.NET的ActiveX控件。右击工具箱,选择自定义工具箱。在COM组件选项卡里选择微软ListView控件,并勾选旁边的复选框(见C)。这样Listview控件就会被添加到工具箱里。

图C

选择微软ListView控件

 

你一把Listview控件放到窗体里,Visual Studio.NET就会生成ActiveX控件的RCW。对其习惯的命名方法是AxInterop.ActiveXControl.dll,所以在这里它被叫做AxInterop.MSComctlLib.dll。

不使用Visual Studio.NET的互用性


现在假设以下你不使用VisualStudio.NET的情形。取得同一个结果的另一种方法是使用.Net框架里一个叫做类型库导入器(tlbimp.exe)的工具。这个工具可以用来把COM库的类型定义转换成.NET组件。

例如,如果你有一个叫做MyCOMComponent.dll的DOM DLL,那么你就可以像下面这样为它创建一个RCW:

Tlbimp  MyCOMComponent.dll  /out:MyRCW.dll


在有ActiveX控件的情况下,你可以使用.NET框架里叫做ActiveX导入器的工具,把ActiveX控件里的类型定义转换成Windows窗体控件。它可以像下面这样从命令行里使用:
Aximp MyOCX.ocx

把它包装起来

如果你在疑惑VisualStudio.NET或者命令行工具是如何生成这些包装函数的,下面就是关键内容。.NET框架类库有一个叫做TypeLibConverter 的类(System.Runtime.IneropServices.TypeLibConverter),它公开了一个叫做ConvertTypeLibToAssembly的方法,这个方法能够被用于编写你自己的工具;它会生成一个RCW。对于ActiveX控件来说也是这样的——AxImporter类(System.Windows.Forms.Design.AxImporter)可以用来生成ActiveX控件的RCW.

内存管理
.NET和COM在架构上的一个主要不同点是内存管理。CLR使用垃圾收集器提供自动内存管理的功能,这个收集器管理着内存的分配和释放。由于这个过程是定期执行的,所以对象不是一用完或者一被设置成Nothing(Visual Basic.NET使用这个,和C#里null的功能一样)就被立即清除掉的。

当RCW不再被使用或者被设置成Nothing的时侯,对象不是立即被清除掉的,而且相对应的COM对象也会驻留在内存中——这可不是你所希望看到的。出现这样的情况就要采取方法一步步地清除内存。要实现这个目的,你可以调用垃圾收集器、调用System.GC.Collect方法,或者——最好的办法是——调用RCW的Marshal.ReleaseComObject方法。

结论
令人振奋的是,作为COM对象存在的代码仍然能够在.NET框架里使用。真是感谢有包装函数类能够作为两个平台的桥梁。有了像Visual Studio.NET这样的工具,这个处理过程已经变简单了,而且对用户几乎是透明的。所以,下一次你要记住:在你使用.NET进行开发的时候,如果需要一个实现功能的COM对象,那就考虑选择COM Interop。在本系列的下一部分里,我们将看看如何在COM里使用.NET组件。