| 操作系统 办公 实用知识 设计 开发 WEB开发 移动开发 数据库 软件工程 网管 安全 管理 信息化 答疑 渠道 |
关于VisiBroker For Delphi的使用一、如何创建服务器对象
现在按照我们上一届讲的生成框架代码,接下来我们在Crb_impl中加入
三、数组对象与简单数据对象的传递 2、不在接口中申明的常量
以上我介绍了一些数据的定义规范,然而我们需要不仅仅是这样的一些比较抽象的接口定义法则,我们要将法则应用到实际的开发中去,那么我们又是如何运用这些法则了,对于接口描述语言的翻译我前面讲到直接使用IDL2PAS就不讲了,以后的章节中也不会在去将如何转换的问题。下面我们实践一下: 编写接口定义一个返回为浮点类型,输入为短整型变量数组对象的方法 typedef short ArrayType[3]; //自定义类型定义长度为3的数组 interface Account { float InputArray(in ArrayType myArray);//输入为整形数组,返回类型为float的方法 }; //服务端程序的处理xxx_impl.pas interface uses SysUtils, CORBA, account_i, account_c; type TAccount = class; TAccount = class(TInterfacedObject, account_i.Account) protected //****************** public constructor Create; function InputArray ( const myArray : account_i.ArrayType): Single; end; implementation uses ServerMain; constructor TAccount.Create; begin inherited; end; function TAccount. InputArray (const myArray : account_i.ArrayType): Single; var j: Integer; begin // account_i.ArrayType是指我们自定义的数组类型在account_I单元中 for j := 0 to 2 do begin Form1.Memo1.Lines.Add(''myArray['' + IntToStr(j) + ''] = '' + IntToStr(myArray[j]) ); //接受从客户端传递过来的数组变量并将其依次加入到主窗体的MEMO中 end; result := random * 100;//返回一个随机数 end; initialization randomize; end. //服务端程序主单元 unit ServerMain; interface uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, Corba, Account_I, Account_C, Account_S, Account_Impl, StdCtrls; type TForm1 = class(TForm) Memo1: TMemo; procedure FormCreate(Sender: TObject); private { private declarations } protected { protected declarations } Acct : Account; // skeleton 对象 procedure InitCorba; public { public declarations } end; var Form1: TForm1; implementation {$R *.dfm} procedure TForm1.InitCorba; begin CorbaInitialize; // Add CORBA server Code Here Acct := TAccountSkeleton.Create(''Array Server'', TAccount.Create); BOA.ObjIsReady(Acct as _Object); end; procedure TForm1.FormCreate(Sender: TObject); begin InitCorba; Memo1.Lines.Add(''Account object created...''); Memo1.Lines.Add(''Server is ready''); end; end. //客户端程序
unit ClientMain; interface uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, Corba, StdCtrls, Account_I, Account_C; type TForm1 = class(TForm) Button1: TButton; Label1: TLabel; procedure FormCreate(Sender: TObject); procedure Button1Click(Sender: TObject); private { private declarations } protected { protected declarations } Acct : Account; myArray : ArrayType; procedure InitCorba; public { public declarations } end; var Form1: TForm1; implementation {$R *.dfm} procedure TForm1.InitCorba; begin CorbaInitialize; Acct := TAccountHelper.bind; end; procedure TForm1.FormCreate(Sender: TObject); var j: Integer; begin InitCorba; for j := 0 to 2 do myArray[j] := (j + 1) * 100; end; procedure TForm1.Button1Click(Sender: TObject); begin Label1.Caption := FormatFloat(''InputArray = $#,##0.00'', Acct.inputArray(myArray)); end; end. 上面的程序实例很简单我就不一一说明了,下面我们来看一个数据访问的实例 //IDL interface Employee { any getEmployeesByName(in string name); }; 接口方法声明单元 //XXX_Impl.pas interface uses SysUtils, CORBA, employee_i, employee_c; type TEmployee = class; TEmployee = class(TInterfacedObject, employee_i.Employee) public constructor Create; function getEmployeesByName ( const name : AnsiString): ANY; end; implementation uses dmEmployee,DMPooler, provider,DSIntf,ServerMain; constructor TEmployee.Create; begin inherited; end; function TEmployee.getEmployeesByName ( const name : AnsiString): ANY; var DM: TdmEmploy; RecsOut: Integer; Options: TGetRecordOptions; begin Options := [grMetaData,grReset]; //must specify meta data DM := ModulePooler.GetModule as TdmEmploy; //Get instance of datamodule from Pool try DM.qryEmployee.Close; DM.qryEmployee.ParamByName(''name'').AsString:= name + ''%''; //显示连接服务器的数量 Inc(Form1.HitCount); Form1.Label1.Caption := Format(''Hit Count = %d'', [Form1.HitCount]); DM.qryEmployee.Open; Result:=DM.proEmployee.GetRecords(-1, RecsOut, Byte(Options)); DM.qryEmployee.Close; finally ModulePooler.FreeModule(DM);//Return instance of DataModule to pool end; end; initialization //将TdmEmploy对象放入共享池中 ModulePooler.ModuleClass := TdmEmploy; end. //共享池的声明单元 主要描述如何提供一个多客户的访问数据提供 unit DMPooler; interface uses SysUtils, Classes, Forms, SyncObjs, Windows; type //本单元用于为每个客户提供一个独立使用的DataModule对象,相当于我们在以前的CORBA DataModule中选择创建的多线程对象一样的功能 TDataModuleClass = class of TDataModule; //定义类 TPooledModule = record//声明记录类型 Module: TDataModule; //继承标准的TdataModule InUse: Boolean; //标明上面继承的TdataModule是否在使用 end; TModulePooler = class private FCSect: TCriticalSection; //允许线程自己改变FModules FModuleClass: TDataModuleClass; //在共享池中类化TDataModule FModules: array of TPooledModule; //定义一个动态的对象记录数组 FSemaphore: THandle; //限定同时使用的用户规则 public property ModuleClass: TDataModuleClass read FModuleClass write FModuleClass; constructor Create; destructor Destroy; override; function GetModule: TDataModule; procedure FreeModule(DataModule: TDataModule); end; const PoolSize = 5; var ModulePooler: TModulePooler = nil; implementation uses Dialogs; { TModulePool } constructor TModulePooler.Create; begin IsMultiThread := True; FCSect := TCriticalSection.Create; FSemaphore := CreateSemaphore(nil, PoolSize, PoolSize, nil); end; destructor TModulePooler.Destroy; begin FCSect.Free; CloseHandle(FSemaphore); end; procedure TModulePooler.FreeModule(DataModule: TDataModule); var I: Integer; begin FCSect.Enter; try for I := 0 to Length(FModules) - 1 do if FModules[I].Module = DataModule then FModules[I].InUse := False; ReleaseSemaphore(FSemaphore, 1, nil); finally FCSect.Leave; end; end; function TModulePooler.GetModule: TDataModule; var I: Integer; begin Result := nil; if WaitForSingleObject(FSemaphore, 5000) = WAIT_TIMEOUT then raise Exception.Create(''Server too busy''); FCSect.Enter; try if Length(FModules) = 0 then begin SetLength(FModules, PoolSize); for I := 0 to PoolSize - 1 do begin FModules[I].InUse := False; FModules[I].Module := FModuleClass.Create(Application); end; end; for I := 0 to Length(FModules) - 1 do if not FModules[I].InUse then begin FModules[I].InUse := True; Result := FModules[I].Module; Break; end; finally FCSect.Leave; end; //检查曾经是否连接 if not Assigned(Result) then raise Exception.Create(''Pool is out of capacity''); end; initialization ModulePooler := TModulePooler.Create; finalization ModulePooler.Free; end. //本单元是一个通用的方法单元,当然您也可以采用其他的方法来完成这样的一个功能 //DataModule单元 unit dmEmployee; interface uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, Db, DBTables, Provider; type TdmEmploy = class(TDataModule) Session1: TSession; EmployeeDatabase: TDatabase; qryEmployee: TQuery; proEmployee: TDataSetProvider; private { Private declarations } public { Public declarations } end; var dmEmploy: TdmEmploy; implementation {$R *.DFM} end. //服务器的主单元 unit ServerMain; interface uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, Grids, DBGrids, Db, DBTables, StdCtrls, Corba, Employee_I, Employee_C, Employee_S, Employee_Impl; type TForm1 = class(TForm) Label1: TLabel; procedure FormCreate(Sender: TObject); private { Private declarations } procedure CorbaInit; public { Public declarations } hitcount : integer; end; var Form1: TForm1; myDBServer : Employee; implementation {$R *.DFM} procedure TForm1.CorbaInit; begin CorbaInitialize; myDBServer := TEmployeeSkeleton.Create(''myServer'', TEmployee.Create); Boa.ObjIsReady( myDBServer as _Object ); end; procedure TForm1.FormCreate(Sender: TObject); begin CorbaInit; end; end. //客户端程序 interface uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, Grids, Corba, Employee_i, Employee_c, Db, DBClient, ExtCtrls, DBCtrls, DBGrids; type TForm1 = class(TForm) Button1: TButton; DBGrid1: TDBGrid; cdsEmployee: TClientDataSet; DataSource1: TDataSource; edtEmployeeName: TEdit; Memo1: TMemo; Label1: TLabel; procedure FormCreate(Sender: TObject); procedure Button1Click(Sender: TObject); private { Private declarations } myEmployee : Employee; public { Public declarations } end; var Form1: TForm1; implementation {$R *.DFM} procedure TForm1.FormCreate(Sender: TObject); begin myEmployee := TEmployeeHelper.bind; end; procedure TForm1.Button1Click(Sender: TObject); begin cdsEmployee.Data := myEmployee.getEmployeesByName(edtEmployeeName.Text); cdsEmployee.Open; end; end. 我想大家应该可以看得懂上面的程序,如果看不懂也不要紧,下一次我将围绕这个实例展开一系列的问题描述并会同时于COM+/MIDAS进行比较说明,为了让大家留下一个思维的空间我在这里就不多说了。还是那一句话下次再见!
今日推荐
|
重点推荐
领军企业技术文库
+更多领军技术文库
最新专题
电子杂志订阅
| ||||||||