前言:
.NET中的代码是不能够直接被COM组件使用的,为了能够在COM组件中使用.NET的代码生成的组件,我们需要创建一个相当于代理的中间介质,它叫做可调用COM包装器(COM callable wrapper (CCW),以下简称为CCW)。下面我们就学习一下这个包装器的一些知识,创建开发能够被COM组件所能使用的.NET的类。
可调用COM包装器:
在通用语言运行时(Common Language Runtime (CLR))下运行的代码我们称之为"受托管代码",这样的代码能够访问到CLR带来得所有服务,比如跨语言、代码安全性和版本支持、垃圾收集等等。而运行在非CLR环境下的代码我们称之为"非托管代码"。因为COM模型是在CLR之前设计出来的,因此COM组件的代码不能够直接运行于CLR提供的基础环境之上,它也就无法享受任何一项由CLR提供的服务。所有的COM组件都是定义在非托管代码范围内的。
托管代码不仅本身运行于CLR,他们(托管代码)还要求与他们相互作用的组件也必须运行于CLR下。因为COM组件不能够运行于CLR,所以COM组件无法被托管代码的组件直接调用。而托管代码也无法直接使用CLR下运行的托管代码。
我们要走出这个困境只有使用代理。代理是一个组件的接口,组件通过这个代理可以完成接收外部命令或是与其他组件发生关系以及其他一些操作。而用在非托管代码调用托管代码的接口则称为CCW。下面我们以一个实例来解释这个模型,下面这幅图中包含一个标准COM组件叫做ComUI.exe,两个.NET组件,分别叫做NETService.dll和Utility.dll,并通过一些必要的技术将它门连接起来。
1.使用CCW来调用托管代码
谨记创建在COM组建中使用的.NET的类的两个前提条件:
1>必须明确的用.NET的代码定义一个接口,而且必须保证这个接口在类中已经实现。
下面就是一个例子,定义了一个接口叫做iFile,并且在类TextFile中将他已经实现。
接口中会实现COM组件的主要功能。CCW保证了.NET与COM组件接口的一致性。
Public Interface iFile
Property Length() As Integer
End Interface
Public Class TextFile
Implements iFile
' details omitted
End Class
2>任何要被COM组件可视(可访问)的类都必须定义为public,因为创建CCW的工具只能够定义类型为public的类。
2.开发部署一个能被COM组件调用的.NET组件
当你创建了一个能被COM调用的.NET装配件后,经过下面三个步骤才能确保你的装配件中的类能够 被COM组件使用:
1.首先为你的装配件创建一个类型库,这个.NET装配件的类型库包含有与COM组件相同的元数据,类型库通常包含在扩展名为.tlb的文件中。类型库中包含的信息使COM组件客户端能够确定类 所在的服务器的详细信息以及这些类的方法、属性及事件等信息。.NET Framework SDK 中包含一个能够创建装配件类型库的工具叫做tlbexp。Tlbexp包含许多选项,可以在命令行(开始-> 程序->Microsoft Visual studio .NET 2003->Visual Studio .NET工具->Visual Studio .NET 2003命令行...)中使用tlbexp/?来查看。其中有一个选项参数是"/out",这个选项参数允许你为装配件生成指定名称的类型库。
例如:为装配件NETServer.dll生成类型库的命令如下:
tlbexp NETServer.dll /out:NETServer.tlb
2.使用装配件注册工具(regasm)
使用这个工具你可以用一个操作来完成生成装配件的类型库并注册它。如果你的.NET开发和COM 开发位于通一台机器上的话,这样做是最简单的。当然这个命令也有很多参数,你可以通过使 用与tblexp相同的办法来查看他们的详细情况。
下面是一个例子,使用这个命令同时创建类型库,并注册:
regasm /tlb:NETServer.tlb NETServer.dll
3. 必须把.NET装配件安装到全局装配件缓存(GAC)中,这个步骤使用命令行工具gacutil;可以使用gacutil/?来查看他的各个选项参数的具体用法。
下面是一个例子:gacutil /i NETServer.dll
到现在为止我们已经说完了如何创建一个COM组建能够调用的.NET装配件了,下面以一个完整的例子来说明整个过程:
1>首先创建一个类库项目:
文件名叫做:NETTemperature.vb(当然你也可以用C#创建)
代码:
1. Public Interface iTemperature
2. Property Celsius() As Double
3. Property Fahrenheit() As Double
4. Function GetCelsius() As Double
5. Function GetFahrenheit() As Double
6. End Interface
7.
8. Public Class NET_Temperature
9. Implements iTemperature
10.
11. Private mdblCelsius As Double
12. Private mdblFahrenheit As Double
13.
14. Public Property Celsius() As Double _
15. Implements iTemperature.Celsius
16. Get
17. Celsius = mdblCelsius
18. End Get
19. Set(ByVal Value As Double)
20. mdblCelsius = Value
21. mdblFahrenheit = ((Value * 9) / 5) + 32
22. End Set
23. End Property
24.
25. Public Property Fahrenheit() As Double _
26. Implements iTemperature.Fahrenheit
27. Get
28. Fahrenheit = mdblFahrenheit
29. End Get
30. Set(ByVal Value As Double)
31. mdblFahrenheit = Value
32. mdblCelsius = ((Value - 32) * 5) / 9
33. End Set
34. End Property
35.
36. Public Function GetCelsius() As Double _
37. Implements iTemperature.GetCelsius
38. GetCelsius = mdblCelsius
39. End Function
40.
41. Public Function GetFahrenheit() As Double _
42. Implements iTemperature.GetFahrenheit
43. GetFahrenheit = mdblFahrenheit
44. End Function
45. End Class
为了使装配件有一些描述信息,我们可以把这个类库项目的AssemblyInfo.vb做一些修改,如下:
1. <Assembly: AssemblyTitle("PhysServer2")>
2. <Assembly: AssemblyDescription(".NET Version of PhysServer")>
然后编译成.DLL文件,然后用前面讲过的三个步骤1.生成类型库;2.注册类型库;3.安装到GAC;
下面就是用vb创建一个程序,使用这个装配件,我这里举一个例子,创建一个VB窗体程序,使用下面的一些控件:
Control Type
Property
Value
Label
Name
lblFahrenheit
Caption
Fahrenheit
TextBox
Name
txtFahrenheit
Text
(blank)
Button
Name
cmdConvertToC
Caption
Convert to C
Label
Name
lblCelsius
Caption
Celsius
TextBox
Name
txtCelsius
Text
(blank)
Button
Name
cmdConvertToF
Caption
Convert to F
窗体样式如下:
然后在vb的IDE环境下点击菜单上的Reference(引用),打开引用对话框,如下:
找到.NET Version of PhysServer,然后选中它(即引用该组件),这样就已经添加了对这个.NET装配件的引用,我们就可以在程序中像使用其他COM组建一样使用这个.NET装配件了。
然后在窗体中添加入下代码编译,执行,看一下效果!
Private moTempClass As PhysServer2.NET_Temperature
Private moTemp As PhysServer2.iTemperature
Private Sub cmdConvertToC_Click()
With moTemp
.Fahrenheit = txtFahrenheit.Text
txtCelsius.Text = .GetCelsius
End With
End Sub
Private Sub cmdConvertToF_Click()
With moTemp
.Celsius = txtCelsius.Text
txtFahrenheit.Text = .GetFahrenheit
End With
End Sub
Private Sub Form_Load()
Set moTempClass = New PhysServer2.NET_Temperature
Set moTemp = moTempClass
End Sub
是不是得到了想要得结果?祝贺你,成功了!
这里只是简单讲述了在非托管代码环境下如何使用托管代码的组件,其中还有很多更深层次的内容本文并没有涉及,旨在抛砖引玉,望大家不吝赐教!由于时间紧促,我在很短的时间内整理出了这篇文章,当中有不妥的地方望大家见谅,这也是本人的处女作,希望大家给一定的鼓励!谢谢
csdn:storm97---YYF于上海