文章详情

  • 游戏榜单
  • 软件榜单
关闭导航
热搜榜
热门下载
热门标签
php爱好者> php文档>delphi(f3)

delphi(f3)

时间:2006-06-10  来源:许我一个信仰

附录C  将程序转变为自动化服务器

自动化是COM的一个方面,您可以利用它从程序中获得额外的收益。本附录示范了一些基本的步骤来选取一个程序(这里是第19章的SQLBuilder),然后向工程添加自动化对象,将程序转换为自动化服务器。之所以选择SQLBuilder,是因为自动化客户可利用SQLBuilder服务器来针对任何数据集生成SQL。

请记住,在运行自动化服务器之前,还需要有自动化客户,即任何请求创建COM对象实例的程序。可创建COM对象实例的工具非常多,包括报表工具、VBA(大部分在Microsoft Office中),以及大部分的Wintel编程语言。

C.1  向工程添加自动化对象

这里不再涉及第19章的SQLBuilder程序的细节,该工程的源代码和编译后的版本都在本书的光盘上。该程序使用了TSession类型的全局变量来从ODBC和BDE注册文件获取数据库名字的列表。当用户选定某个数据库名时,将以同样的方式获取该数据库中可用的表名。用户选取一个表时,将从TDataSet.Fields集合读入字段定义并显示在TValueListEditor对象中,该对象是网格形状的、基于TStrings的控件。在字段值已知的情况下,可利用Format函数对定义了参数的SQL语句进行简单的字符串替换。就是这样。

如果您已经读过本书前面的部分,那么您已经掌握了这些技巧,因此我们不再涉及SQLBuilder工程的更多细节。从这里开始,我们将进行一些必要的步骤,向该工程添加自动化对象。

C.1.1  使用自动化对象向导

现在打开原来的SQLBuilder工程,开始向它添加自动化对象。打开工程后,在Delphi中单击File | New | Other菜单项。然后在New Items对话框中选择ActiveX属性页,并选择其中的Automation Object图标(如图C.1所示)。这里使用的CoClass名为Builder,并采用了缺省的实例化和线程模型(关于实例化和线程模型的特定细节,请参考第15章)。单击OK生成类型库并触发类型库编辑器。

我们将使用类型库编辑器来定义自动化服务器的接口,并更新类型库和包含TBuilder类的Pascal源文件,该类是服务器的包裹类。

C.1.2  在类型库编辑器中定义接口

在向导中单击OK后,将定义一个包裹类,该类继承了TAutoObject类,并实现了IBuilder接口。在光盘上,相应的文件名是UBuilder.pas。当结束自动化接口定义后,类型库编辑器(见图C.2)中的Refresh按钮将把声明和定义添加到Pascal包裹类的单元。

图C.1  自动化对象向导小应用程序

图C.2  类型库编辑器以及TBuilder类的定义

对于该自动化对象,我们将定义一些方法和特性,以便设置数据库名和表名,获取数据库名和表名的列表,以及字段和SQL文本的管理等。按下列步骤,可以在类型库编辑器中定义接口。

1.       在类型库编辑器中,单击New Property工具栏按钮(或右键单击IBuilder接口,从接口的上下文菜单中选择该菜单项,参考图C.2)添加DatabaseName特性。

2.       在Attributes属性页上(在图C.2中也可以看到),将Name修改为DatabaseName,将类型修改为BSTR,对读写定义二者都进行同样的修改。

3.       对TableName特性重复步骤2。这两个特性将用于修改选定的数据库名和表名。

4.       添加两个方法(单击Methods工具栏按钮),将其命名为GetTableNames和GetDatabaseNames。TStrings对象可返回分隔好的文本,因此我们可以利用TStrings的Text特性将所有的列表项作为一个字符串传递。

5.       在Parameters属性页上将Type设置为BSTR*,这是指向BSTR,即宽字符串的指针,并将Modifier修改为[out,retval]。BSTR*指针用于返回类型。现在我们只用一个方法调用就可以得到所有的数据库名和方法名。

6.       重复步骤5,定义GetFieldsList和GetSQLText方法。它们在自动化服务器中都存储为TStrings,因此声明步骤与5相同(看一下SQLBuilder工程,可以发现字段在TValueListEditor中,而SQL文本在TMemo对象中。两个控件都有TStrings特性)。

7.       将SetFieldsList在Parameters属性页上定义为[in] BSTR。该方法可用于更新对字段和值的列表的修改。

8.       添加一个可用于读写的QueryType特性,它使用整数来修改查询类型,在服务器中用TRadioGroup来表示。

9.       最后,定义方法TestQuery,它没有参数。我们将使用TestQuery对服务器进行查询。

10.   单击Refresh Implementation工具栏按钮。最后的结果是在包含TBuilder类的源代码单元中生成的声明和定义。

如果一切正常,类声明如下:

TBuilder = class(TAutoObject, IBuilder)

protected

function Get_DatabaseName: WideString; safecall;

function Get_TableName: WideString; safecall;

function GetDatabaseNames: WideString; safecall;

function GetFieldsList: WideString; safecall;

function GetSQLText: WideString; safecall;

function GetTableNames: WideString; safecall;

procedure Set_DatabaseName(const Value: WideString);

safecall;

procedure Set_TableName(const Value: WideString); safecall;

procedure SetFieldsList(const FieldsList: WideString);

safecall;

procedure TestQuery; safecall;

function Get_QueryType: SYSINT; safecall;

procedure Set_QueryType(Value: SYSINT); safecall;

{ Protected declarations }

end;

这里没有什么真正值得惊奇的东西。看一下数据类型,可以看到都已经转换成了Delphi中的别名。过程传递常量参数而函数则返回适当的类型(还会生成.tlb文件,但通常应该避免直接修改该文件)。下一步是实现接口。因为工作已经在程序中完成,每个接口的实现都很简单。

C.1.3  实现接口

大多数方法都只对服务器程序主窗体的简单文本进行操作,或者是每个特定控件所包含的TStrings特性。完整的实现代码如下,几乎不需要什么解释。

uses ComServ, UFormMain;

 

function TBuilder.Get_DatabaseName: WideString;

begin

result := Form1.ComboBox1.Text;

end;

 

function TBuilder.Get_TableName: WideString;

begin

result := Form1.ComboBox2.Text;

end;

 

function TBuilder.GetDatabaseNames: WideString;

begin

result := Form1.ComboBox1.Items.Text;

end;

 

function TBuilder.GetFieldsList: WideString;

begin

result := Form1.ValueListEditor1.Strings.Text;

end;

 

function TBuilder.GetSQLText: WideString;

begin

result := Form1.Memo1.Lines.Text;

end;

 

function TBuilder.GetTableNames: WideString;

begin

result := Form1.ComboBox2.Items.Text;

end;

 

procedure TBuilder.Set_DatabaseName(const Value: WideString);

begin

Form1.ComboBox1.Text := Value;

Form1.ComboBox1Change(Self);

end;

 

procedure TBuilder.Set_TableName(const Value: WideString);

begin

Form1.ComboBox2.Text := Value;

Form1.ComboBox2Change(Self);

end;

 

procedure TBuilder.SetFieldsList(const FieldsList: WideString);

begin

Form1.ValueListEditor1.Strings.Text := FieldsList;

end;

 

procedure TBuilder.TestQuery;

begin

Form1.RunSQL;

end;

 

function TBuilder.Get_QueryType: SYSINT;

begin

result := Form1.RadioGroup1.ItemIndex;

end;

 

procedure TBuilder.Set_QueryType(Value: SYSINT);

begin

Form1.RadioGroup1.ItemIndex := Value;

end;

从代码显然可以看出,每个方法的实现都只有一两行代码。例如,稍复杂的是Set_TableName方法,它是TableName特性的写方法。该方法直接把表名赋值给TComboBox.Items.Text特性,然后手工调用相关联的OnChange事件处理程序;该处理程序确保用新表的字段定义列表来更新TValueFieldList控件。

在具有工业水准的程序中,需要进行一些检查。例如,当设置TableName特性时,需要验证要设置的表名是有效的。虽然组合框已经提供了该功能并能够自动生成异常,但最好在客户端捕获异常并让用户重新选择另一个表。

C.1.4  运行服务器来注册类型库

在使用服务器之前,需要注册类型库。最简单的注册方法是将服务器作为单独的程序运行。也可以使用类型库编辑器中的Register Type Library工具栏按钮进行注册。

注意:Microsoft正致力在.NET框架中减少注册类型库的需要。这可是件好事情。

C.2  建立测试程序

在服务器程序中建立的自动化对象继承自TOleServer,它是TComponent的子类。定义了一个Register方法,这样可以方便地注册服务器组件,使得该组件易于使用。要把该自动化服务器安装到VCL中,可以选择Project | Import Type Library菜单项并单击Add按钮。找到服务器的.tlb文件,然后单击Open按钮。在Import Type Library对话框中,单击Install按钮。Install按钮将提示您选择一个包。对于我们的目的来说,dclusr60.bpl包是很方便的。建立该包。现在您就可以建立测试程序了。

任何程序都可以用于测试该服务器,关键在于要创建服务器的实例,然后调用方法并访问特性以确保一切都工作正确。下面的步骤提供了测试新的组件化服务器的一种可能的途径。

1.       缺省情况下,自动化服务器组件安装到组件面板的Servers属性页,除非修改自动生成的Register过程。

2.       在Delphi中,创建新的应用程序并将TBuilder组件拖放到主窗体上。

3.       在FormCreate事件方法中连接到服务器。例如,如果使用了缺省的名字Builder1,那么可以使用Builder1.Connect来启动自动化服务器程序。

4.       最后,添加代码来测试服务器。测试代码如下,对SQLBuilder自动化服务器的各项功能进行了简要测试。

Screen.Cursor := crHourglass;

try

try

Form2.Enabled := False;

Memo1.Lines.Text := Builder1.GetDatabaseNames;

Sleep( 2000 );

Builder1.DatabaseName := 'DBDEMOS';

Sleep( 1000 );

Memo1.Lines.Text := Builder1.GetTableNames;

Sleep(1000);

Builder1.QueryType := 0;

Builder1.TableName := 'customer.db';

Memo1.Lines.Text := Builder1.GetSQLText;

Builder1.TestQuery;

finally

Form2.Enabled := True;

end;

finally

Screen.Cursor := crDefault;

end;

将上述代码添加到响应鼠标单击的事件方法中,从服务器获取的数据则显示在TMemo控件中。代码中调用了Sleep暂停了一下,这样可以使用户跟上程序的响应。代码非常直观:上面列出的代码改变了DatabaseName、TableName,并请求所生成的SQL文本。最后调用了TestQuery方法。如果运行示例程序(定义在TestAuto.dpr中),可以先找到SQLBuilder程序的Data属性页,看一下从DBDEMOS数据库返回的顾客数据。

代码的其余部分用处不大。有用的代码不见得冗长。在掌握用法之后,TStrings对象是非常简单的;从示例可以看出,文本就存储在TStrings对象中。在设计类和服务器时保持小而扼要的接口,就能达到这种简单性。

C.3  小  结

如果您读到了这里,说明您已经顺利地创建并测试了服务器程序。Delphi通过隐藏类型库代码和IDL,使得创建和使用COM对象,如自动化服务器,变得相对容易。创建自动化服务器的实例也很容易,因为Delphi可以使自动化服务器组件化。如果把服务器变成组件,那么无论自己或他人使用,都会非常方便。

要记住,自动化是一种手段,您可以通过它在开发工具之间共享应用程序。在不久的将来,自动化将成为最大化的实现工具的重用的一条好途径。

 

相关阅读 更多 +
排行榜 更多 +
谷歌卫星地图免费版下载

谷歌卫星地图免费版下载

生活实用 下载
谷歌卫星地图免费版下载

谷歌卫星地图免费版下载

生活实用 下载
kingsofpool官方正版下载

kingsofpool官方正版下载

赛车竞速 下载