第二部分:在.NET里使用vfp编写的COM组件
Fox能够灵活、直观、快速处理数据,使得它非常适合应用在业务逻辑层次。从Visual FoxPro 5开始,微软不断加强Visual FoxPro 的COM组件开发上能力。简单归纳一下Visual FoxPro 在COM组件编写的特点:
- 全新的运行时刻库:VFPnT.DLL(n代表版本号)。在这个运行库中,删除了大量老式的和界面控制元素,更小巧、更稳定、更快速。
- 全新的SESSION对象。在多线程状态下提供很好的隔离性。
- 内置对XML的支持,方便了多层应用中记录集(游标)的传递。
- 通过ExecScript() 函数,提供了动态执行多行语句的能力。
- 完全支持COM+标准。
用Fox编写COM组件是一件愉快的事情,.NET提供了对COM组件的调用支持,于是我们将快乐在.NET里继续。
在Visual FoxPro里编写一个COM组件:(CODE#5)
DEFINE CLASS Customer as FoxBaseClass olepublic
*继承至自定义的 FoxBase 类
*声明时使用 olepublic 关键字,告诉编译器定义的是一个COM组件
PROCEDURE Init()
this.DataBasePath=SUBSTR(SYS(2004),1,RAT("\",SYS(2004),2))+"data\"
DODEFAULT()
ENDPROC
* GetCountry() 返回客户说在国家的列表,结果用XML表示
FUNCTION GetCountry() as String
LOCAL cXml as String
SELECT distinc(country) as country FROM customer INTO CURSOR Temp
CURSORTOXML("Temp","cXml",1,16,0,"1")
USE IN temp
RETURN cXml
ENDFUNC
* GetCustomer() 返回指定国家的客户列表,结果用XML表示
FUNCTION GetCustomer(cCountry as String) as String
LOCAL cXml as String
SELECT * FROM customer WHERE Country=m.cCountry INTO CURSOR Temp
CURSORTOXML("Temp","cXml",1,16,0,"1")
USE IN temp
RETURN cXml
ENDFUNC
*合计指定国家的销售净额。这里通过调用DBC里的存储过程取得结果
FUNCTION GetSumOrderNet(cCountry as String) as Double
RETURN Get_Sum_Order_Net(m.cCountry)
ENDFUNC
*写入日志的接口。这里通过调用DBC里的存储过程取得结果
FUNCTION LogIt(cMsg as String) as Boolean
logMsg(cMsg)
RETURN .t.
ENDFUNC
ENDDEFINE
接着,我们要编译代码,生成一个COM组件。假设将以上代码放在一个名为foxclass.prg的文件里,使用下面的语句,就能得到进程内COM组件:(CODE#6)
*先将foxclass.prg放入一个名为foxWebService的项目(Project)里,如果此项目不存在,就生成项目
BUILD PROJECT foxWebService FROM foxclass
*编译foxWebService项目成为一个COM组件(foxwenservice.dll),并且在系统里注册它。
BUILD MTDLL foxWebService FROM foxWebService recompile
在.NET里,如果希望引用一个非托管的COM组件,就必须为非托管COM提供一个.NET定义。可以使用.NET SDK 里的TLBIMP工具程序把一个非托管的COM类型库转换成为.NET的元数据,这种元数据实际上就是一个可以被任何托管代码访问的容器类,把原来的非托管代码包装起来。(CODE#7)
在命令提示符里执行,如下语句:
将 H:\NET\fox_com\foxwebservice.dll 转化为 .NET的,存放在H:\NET\ foxwebservice.dll里
TlbImp /OUT:net_fox_com.dll foxwebservice.dll
如果你不是很清楚TlbImp是怎样安排net_fox_com里面的对象,请使用.NET SDK提供的ildasm.exe工具查看net_fox_com.dll的结构。这样,我们就可以在C# 程序里使用我们刚才编写的 COM 组件了:(CODE#8)
net_fox_com.CustomerClass obis= new net_fox_com.CustomerClass();
obis.GetCountry();
obis.GetSumOrderNet(“UK”);
如果C# 程序用到了net_fox_com中的类定,可以这样编译C#代码,在命令提示符里执行这样的代码:(CODE#9)
csc /t:winexe com_client_sample.cs /r:net_fox_com.dll
特别之处在于加入了对net_fox_com.dll的引用。还有需要注意的是,务必把net_fox_com.dll文件放在.NET的搜索路径里,不然执行应用程序时会报错。我的做法是将EXE文件与net_fox_com.dll放在同一个目录里面;另外,如果COM组件发生了改变,必须重新生成net_fox_com.dll,并且重新编译C#代码。
.NET对COM体系的平稳过渡,体现了微软对开发人员的尊重。试一试,你会发现一切是如此简单……