编写最简单的DCOM中间层:
■创建应用服务器
要创建一个多层Client/Server应用程序,首先要创建应用服务器,然后注册或安装应用服务器,只有应用服务器已注册并且正在运行的情况下,才能创建客户程序。对于客户程序来说,既可以在设计期连接应用服务器,也可以在运行期连接应用服务器。注意:如果客户程序与应用服务器不在同一个系统中,必须在客户计算机上注册或安装应用服务器,这样,在设计期就可以连接应用服务器。创建应用服务器的一般步骤是:
1.使用File选单上的New Application命令开始一个新项目,然后使用File选单上的New命令,选取Multi页。如果通过DCOM方式访问服务器,则选择远程数据模块“Remote Data Module”;如果通过CORBA方式访问服务器,则选择CORBA数据模块“CORBA Data Module”。
2.把一个数据集构件,如TTable、TQuery或TStoredProc放到远程数据模块上并进行相关设置,使得它们能访问远程的SQL数据库。注意尽量不要把TDatabase构件放到远程数据模块上,因为这可能引起名称冲突,如果需要用TDatabase构件来连接SQL数据库,建议把TDatabase构件放到另一个数据模块上,然后引用这个数据模块的单元文件。
3.把TDataSetProvider或TProvider构件放到远程数据模块上,有一个数据集构件,就要有一个TDataSetProvider或TProvider构件与之对应。然后,用鼠标右键单击TDataSetProvider或TProvider构件,在弹出的选单中选择“ExportFrom in Data Module”命令,这是为了引出IProvider接口,在类型库中注册。
4.设置TDataSetProvider或TProvider构件的DataSet属性指定要访问的数据库,实际上就是第二步所放的数据集构件。
5.编写代码,实现规则。
6.保存、编译、注册并安装应用服务器。对于DCOM协议而言,应用服务器就好像一个自动化服务器一样,必须像ActiveX或COM服务器那样注册。如果使用CORBA,可以不注册,但最好注册。如果要使客户程序对服务器接口的调用在运行期是动态确定的,就要在接口库(Interface Repository)中安装服务器的接口。如果要使客户程序能自动激活应用服务器(如果还没有运行的话),应用服务器就必须用OAD(Object Activation Daemon)进行注册。
7.如果应用服务器没有使用DCOM,必须安装有关的运行期软件,因为其他连接方式需要这些运行期软件的支持。对于CORBA来说,需要安装VisiBroker ORB。
■远程数据模块
应用服务器的关键部件是远程数据模块。Delphi 4支持三种类型的远程数据模块,分别是TRemoteDataModule、TMTSDataModule和TCorbaDataModule。其中TRemoteDataModule在生成DCOM应用时加入,在设置其属性的“Remote Data Module Wizard”对话框中,在“Class Name”框内键入远程数据模块的类名,不必以T打头。Delphi 将以此名生成一个TRemoteDataModule的派生类,并以此名生成有关接口。在“Threading Model”框内选择一种线程模式,在“Instancing”框内选择是否根据客户的请求生成远程数据模块的多个实例。
在CORBA应用中,要加入一个TCorbaDataModule类型的远程数据模块,在“CORBA Data Module Wizard”对话框中需要在“Class Name”框内键入远程数据模块的类名, Delphi将生成一个TCorbaDataModule的派生类,并以此名生成有关接口。在“Threading Model”框内选择一种线程模式。在“Instancing”框内指定应用服务器怎样创建远程数据模块的实例,可以选“Shared Instance”或者“Instance-Per-Client”。如果选“Shared Instance”,应用服务器只创建远程数据模块的一个实例来处理所有客户的请求。如果选“Instance-Per-Client”,每当一个客户试图连接时,远程数据模块都会生成一个实例,只要客户与应用服务器的连接没有断开,远程数据模块的实例就一直存在。
■创建客户程序
下面我们将开始设计客户端程序。创建客户程序的一般步骤是:
1.使用“File”选单上的“New Application”命令开始一个新的项目,然后使用“File”选单上的“New”命令,再双击“Data Module”图标加入一个数据模块。
2.把一个或几个MIDAS连接构件如TDCOMConnection、TCorbaConnection、TRemoteServer或TMIDASConnection加到数据模块上。至于究竟选择哪一种MIDAS连接构件,这取决于通讯协议。
3.设置有关属性指定和连接应用服务器,这与具体的MIDAS连接构件有关。
4.把一个或几个TClientDataSet构件放到数据模块上,设置RemoteServer属性指定一个MIDAS连接构件,设置ProviderName属性指定应用服务器上的TDataSetResolver 或TProvider构件,这样,客户程序就可以通过IProvider接口与应用服务器通讯。
5.把一个TDataSource构件放到数据模块上,设置它的DataSet属性指定TClientDataSet构件,再把一个数据控件放到窗体上,设置它的DataSource属性指定TDataSource构件。
■与应用服务器连接
要建立与应用服务器的连接,客户程序必须使用一个或几个MIDAS连接构件。
要使用DCOM方式来连接应用服务器,就要用到TDCOMConnection构件。TDCOMConnection构件的ComputerName属性用于指定应用服务器所在的计算机。ComputerName属性一般设为计算机的主机名或IP地址,如果指定的主机名或IP地址是非法的或者没有找到,TDCOMConnection就会触发异常。如果客户程序需要在运行期间动态地选择应用服务器,最好不要用ComputerName属性来切换,我们可以加入一个TSimpleObjectBroker构件,再由ObjectBroker属性指定这个TSimpleObjectBroker构件。
要使用CORBA方式连接应用服务器,就要用到TCorbaConnection构件。对于CORBA方式来说,只需要设置RepositoryID属性标识CORBA数据模块的接口,因为局域网中的智能代理(Smart Agent)会自动定位一个可用的应用服务器。如果想指定一个特定的应用服务器,就要设置HostName属性指定应用服务器的主机名或IP地址。TCorbaConnection构件可以通过两种方式获得应用服务器上CORBA数据模块的接口:如果要使用静态联编方式,必须把_TLB.pas文件(由类型库编辑器生成)加到客户程序中,静态联编方式不仅能够在编译期进行类型检查,而且运行速度较快。如果要使用动态联编方式,CORBA数据模块的接口必须用InterfaceRepository注册。
■标识服务器
如果使用DCOM方式来连接应用服务器,可以通过ServerName属性或ServerGUID属性来标识应用服务器。其中,ServerName用于指定应用服务器,实际上就是一个已注册的OLE自动化对象名。ServerGUID属性用于指定远程数据模块的全局识别号。如果合法设置了ServerName属性,ServerGUID属性会自动被设置。
如果使用CORBA方式来连接应用服务器,就要用RepositoryID属性来标识应用服务器上CORBA数据模块的接口。
如果客户程序需要在运行期间动态地选择应用服务器,最好用TSimpleObjectBroker构件来切换,而不使用ComputerName属性。TSimpleObjectBroker能够自动维护一个可用的应用服务器的列表。当MIDAS连接构件需要连接一个应用服务器时,它就向TSimpleObjectBroker提出申请,TSimpleObjectBroker一般会随机提供一个应用服务器。如果TSimpleObjectBroker提供的应用服务器无法工作,TSimpleObjectBroker会再换一个,直到MIDAS连接构件与应用服务器建立连接为止。一旦MIDAS连接构件与应用服务器建立了连接,它会自动把应用服务器的有关情况保存到有关属性中,如ComputerName、Address或Host等,因为MIDAS连接构件有可能会断开连接,以后又要再次连接,这时候就不必再向TSimpleObjectBroker提出申请。在使用CORBA方式的情况下,不要用TSimpleObjectBroker构件,因为此方式有自己专门的中介服务。
■调用服务器上的接口
通过TClientDataSet的Provider属性可以获得IProvider接口。其实,大部分情况下并不需要直接调用IProvider接口,因为对IProvider接口的调用已经封装在TClientDataSet的属性和方法中,惟一的例外是,DataRequest函数只能通过IProvider接口调用。通过MIDAS连接构件的AppServer属性可以获得应用服务器上远程数据模块的接口,通过此接口,我们可以调用远程数据模块的方法,由于动态联编在运行期实际调用时有可能失败,并且执行速度没有静态联编快,因此,如果用DCOM或CORBA作为通讯协议连接应用服务器时,最好采用静态联编方式来访问远程数据模块的接口,方法就是用特定的接口类型对AppServer属性进行强制类型转换。假设远程数据模块的接口叫IMyAppServer(它的上级是IDataBroker),程序示例如下:
With MyConnection.AppServer as IMyAppServerdo
SpecialMethod(x,y);
上面这行代码适合于DCOM方式,下面这行代码适合于CORBA方式:
With IUnknown(MyConnection.AppServer) as IMyAppServerdo
SpecialMethod(x,y);
对于DCOM方式来说,要使用静态联编方式调用远程数据模块的接口,它的类型库必须在客户端注册。要注册类型库,可以调用DELPHI4/BIN目录中的TREGSVR.EXE。对于CORBA方式来说,要使用静态联编方式调用远程数据模块的接口,必须在客户程序中引用类型库编辑器生成的_TLB.pas文件。
■自定义应用服务器
MIDAS的结构是非常灵活的,可以从两个方面来自定义应用服务器,一是扩展远程数据模块的接口,二是使用自定义的数据集。
远程数据模块是应用服务器的核心部件,它提供了应用服务器与客户程序通讯的基本接口,除非客户程序直接调用IProvider接口。如果应用服务器使用MTS类型的远程数据模块,客户程序只能通过远程数据模块的接口与应用服务器进行通讯。如果试图绕过MTS代理,就会使事务无效,特别是,由于MTS类型的远程数据模块可以与状态无关,这时候如果绕过MTS代理,有可能导致程序崩溃。同样,单实例模式的CORBA数据模块也是与状态无关的,也存在着上述问题。为了使客户程序能够方便地访问MTS或CORBA数据模块(因为这时候没有IProvider接口),必须对远程数据模块的接口进行扩展,添加一些方法让客户程序调用。MTS或CORBA数据模块的接口都是从IDataBroker继承下来的。要向接口中加入新的属性或方法,可以有两种操作方式:一是使用“Edit”选单上的“Add to Interface”命令,弹出“Add to Interface”对话框;二是使用“View”选单上的“Type Library”命令打开类型库编辑器,在类型库编辑器中选择接口节点,加入了一个新的成员后,并设置相关属性。要说明的是,对于CORBA类型的远程数据模块的接口来说,许多属性是无效的。对于基于COM的远程数据模块TRemoteDataModule来说,新的成员将出现在接口的实现单元和类型库的描述文件中。对于基于CORBA的远程数据模块(TCorbaDataModule)来说,新的成员除了加到接口的实现单元中外,还会自动生成一个_TLB单元。如果客户程序需要访问基于CORBA远程数据模块,必须引用这个单元。另外,可以让类型库编辑器生成IDL脚本,然后用Interface Repository和Object Activation Daemon来注册接口。客户程序可以通过MIDAS连接构件的AppServer属性获取远程数据模块的接口,然后通过接口调用远程数据模块的方法。
通过以上步骤,我们就可以在Delphi中轻松实现DCOM与CORBA的设计工作