继昨天晚上一文:http://blog.csdn.net/yxf/archive/2006/09/28/1303281.aspx ,现在写写用Delphi来编写客户端的方法。同样还是调用昨晚的libss.dll。
1. 新建个Console Application,叫SampleService.Invoker。
2. File->New->Other, Web Services/WSDL Importer,在Location of WSDL File or URL处填上http://localhost/MyServices/SampleService/libss.dll/wsdl/ISampleService,然后点击Finish,然后再点击Finish,接着把生成的单元保存成IComplexOperatorsUnit.pas。
下面是生成的单元的内容:
//
************************************************************************
//
// The types declared in this file were generated from data read from the
// WSDL File described below:
// WSDL : http: // localhost / MyServices / SampleService / libss.dll / wsdl / ISampleService
// Encoding : utf - 8
// Version : 1.0
// ( 2006 - 9 - 29 10 : 03 : 31 - 16.03 . 2006 )
// ************************************************************************ //
unit ISampleServiceUnit;
interface
uses InvokeRegistry, SOAPHTTPClient, Types, XSBuiltIns;
type
// ************************************************************************ //
// The following types, referred to in the WSDL document are not being represented
// in this file. They are either aliases[@] of other types represented or were referred
// to but never[!] declared in the document. The types from the latter category
// typically map to predefined / known XML or Borland types; however, they could also
// indicate incorrect WSDL documents that failed to declare or import a schema type.
// ************************************************************************ //
// !: double - " http://www.w3.org/2001/XMLSchema "
// !: int - " http://www.w3.org/2001/XMLSchema "
// [WARNINGS] ************************************************************** //
// Unable to sort type ' TClassA' due to circular reference!
// ************************************************************************ //
TComplex = class ; { " urn:SampleServiceIntf " }
TExtraData = class ; { " urn:SampleServiceIntf " }
TLoopable = class ; { " urn:SampleServiceIntf " }
TClassA = class ; { " urn:SampleServiceIntf " }
TClassB = class ; { " urn:SampleServiceIntf " }
// ************************************************************************ //
// Namespace : urn:SampleServiceIntf
// ************************************************************************ //
TComplex = class (TRemotable)
private
FR: Double ;
FI: Double ;
published
property R: Double read FR write FR;
property I: Double read FI write FI;
end ;
// ************************************************************************ //
// Namespace : urn:SampleServiceIntf
// ************************************************************************ //
TExtraData = class (TRemotable)
private
FX: Integer ;
published
property X: Integer read FX write FX;
end ;
// ************************************************************************ //
// Namespace : urn:SampleServiceIntf
// ************************************************************************ //
TLoopable = class (TRemotable)
private
FData: TExtraData;
FNext: TLoopable;
public
destructor Destroy; override;
published
property Data: TExtraData read FData write FData;
property Next : TLoopable read FNext write FNext;
end ;
// ************************************************************************ //
// Namespace : urn:SampleServiceIntf
// ************************************************************************ //
TClassA = class (TRemotable)
private
Fref: TClassB;
public
destructor Destroy; override;
published
property ref: TClassB read Fref write Fref;
end ;
// ************************************************************************ //
// Namespace : urn:SampleServiceIntf
// ************************************************************************ //
TClassB = class (TRemotable)
private
Fref: TClassA;
public
destructor Destroy; override;
published
property ref: TClassA read Fref write Fref;
end ;
// ************************************************************************ //
// Namespace : urn:SampleServiceIntf - ISampleService
// soapAction: urn:SampleServiceIntf - ISampleService#%operationName%
// transport : http: // schemas.xmlsoap.org / soap / http
// style : rpc
// binding : ISampleServicebinding
// service : ISampleServiceservice
// port : ISampleServicePort
// URL : http: // localhost / MyServices / SampleService / libss.dll / soap / ISampleService
// ************************************************************************ //
ISampleService = interface (IInvokable)
[ ' {A454ABF4-3610-70C0-E88F-F2F022F2A747}']
function ComplexAdd( const a: TComplex; const b: TComplex): TComplex; stdcall;
function Loop ( const Level: Integer ): TLoopable; stdcall;
function GetClassAB: TClassA; stdcall;
end ;
function GetISampleService(UseWSDL: Boolean = System.False; Addr: string = ' '; HTTPRIO: THTTPRIO = nil): ISampleService;
implementation
function GetISampleService(UseWSDL: Boolean ; Addr: string ; HTTPRIO: THTTPRIO): ISampleService;
const
defWSDL = ' http://localhost/MyServices/SampleService/libss.dll/wsdl/ISampleService';
defURL = ' http://localhost/MyServices/SampleService/libss.dll/soap/ISampleService';
defSvc = ' ISampleServiceservice';
defPrt = ' ISampleServicePort';
var
RIO: THTTPRIO;
begin
Result : = nil;
if (Addr = ' ') then
begin
if UseWSDL then
Addr : = defWSDL
else
Addr : = defURL;
end ;
if HTTPRIO = nil then
RIO : = THTTPRIO.Create(nil)
else
RIO : = HTTPRIO;
try
Result : = (RIO as ISampleService);
if UseWSDL then
begin
RIO.WSDLLocation : = Addr;
RIO.Service : = defSvc;
RIO.Port : = defPrt;
end else
RIO.URL : = Addr;
finally
if (Result = nil) and (HTTPRIO = nil) then
RIO.Free;
end ;
end ;
destructor TLoopable.Destroy;
begin
if Assigned(FData) then
FData.Free;
if Assigned(FNext) then
FNext.Free;
inherited Destroy;
end ;
destructor TClassA.Destroy;
begin
if Assigned(Fref) then
Fref.Free;
inherited Destroy;
end ;
destructor TClassB.Destroy;
begin
if Assigned(Fref) then
Fref.Free;
inherited Destroy;
end ;
initialization
InvRegistry.RegisterInterface(TypeInfo(ISampleService), ' urn:SampleServiceIntf-ISampleService', 'utf-8');
InvRegistry.RegisterDefaultSOAPAction(TypeInfo(ISampleService), ' urn:SampleServiceIntf-ISampleService#%operationName%');
RemClassRegistry.RegisterXSClass(TComplex, ' urn:SampleServiceIntf', 'TComplex');
RemClassRegistry.RegisterXSClass(TExtraData, ' urn:SampleServiceIntf', 'TExtraData');
RemClassRegistry.RegisterXSClass(TLoopable, ' urn:SampleServiceIntf', 'TLoopable');
RemClassRegistry.RegisterXSClass(TClassA, ' urn:SampleServiceIntf', 'TClassA');
RemClassRegistry.RegisterXSClass(TClassB, ' urn:SampleServiceIntf', 'TClassB');
end .
// The types declared in this file were generated from data read from the
// WSDL File described below:
// WSDL : http: // localhost / MyServices / SampleService / libss.dll / wsdl / ISampleService
// Encoding : utf - 8
// Version : 1.0
// ( 2006 - 9 - 29 10 : 03 : 31 - 16.03 . 2006 )
// ************************************************************************ //
unit ISampleServiceUnit;
interface
uses InvokeRegistry, SOAPHTTPClient, Types, XSBuiltIns;
type
// ************************************************************************ //
// The following types, referred to in the WSDL document are not being represented
// in this file. They are either aliases[@] of other types represented or were referred
// to but never[!] declared in the document. The types from the latter category
// typically map to predefined / known XML or Borland types; however, they could also
// indicate incorrect WSDL documents that failed to declare or import a schema type.
// ************************************************************************ //
// !: double - " http://www.w3.org/2001/XMLSchema "
// !: int - " http://www.w3.org/2001/XMLSchema "
// [WARNINGS] ************************************************************** //
// Unable to sort type ' TClassA' due to circular reference!
// ************************************************************************ //
TComplex = class ; { " urn:SampleServiceIntf " }
TExtraData = class ; { " urn:SampleServiceIntf " }
TLoopable = class ; { " urn:SampleServiceIntf " }
TClassA = class ; { " urn:SampleServiceIntf " }
TClassB = class ; { " urn:SampleServiceIntf " }
// ************************************************************************ //
// Namespace : urn:SampleServiceIntf
// ************************************************************************ //
TComplex = class (TRemotable)
private
FR: Double ;
FI: Double ;
published
property R: Double read FR write FR;
property I: Double read FI write FI;
end ;
// ************************************************************************ //
// Namespace : urn:SampleServiceIntf
// ************************************************************************ //
TExtraData = class (TRemotable)
private
FX: Integer ;
published
property X: Integer read FX write FX;
end ;
// ************************************************************************ //
// Namespace : urn:SampleServiceIntf
// ************************************************************************ //
TLoopable = class (TRemotable)
private
FData: TExtraData;
FNext: TLoopable;
public
destructor Destroy; override;
published
property Data: TExtraData read FData write FData;
property Next : TLoopable read FNext write FNext;
end ;
// ************************************************************************ //
// Namespace : urn:SampleServiceIntf
// ************************************************************************ //
TClassA = class (TRemotable)
private
Fref: TClassB;
public
destructor Destroy; override;
published
property ref: TClassB read Fref write Fref;
end ;
// ************************************************************************ //
// Namespace : urn:SampleServiceIntf
// ************************************************************************ //
TClassB = class (TRemotable)
private
Fref: TClassA;
public
destructor Destroy; override;
published
property ref: TClassA read Fref write Fref;
end ;
// ************************************************************************ //
// Namespace : urn:SampleServiceIntf - ISampleService
// soapAction: urn:SampleServiceIntf - ISampleService#%operationName%
// transport : http: // schemas.xmlsoap.org / soap / http
// style : rpc
// binding : ISampleServicebinding
// service : ISampleServiceservice
// port : ISampleServicePort
// URL : http: // localhost / MyServices / SampleService / libss.dll / soap / ISampleService
// ************************************************************************ //
ISampleService = interface (IInvokable)
[ ' {A454ABF4-3610-70C0-E88F-F2F022F2A747}']
function ComplexAdd( const a: TComplex; const b: TComplex): TComplex; stdcall;
function Loop ( const Level: Integer ): TLoopable; stdcall;
function GetClassAB: TClassA; stdcall;
end ;
function GetISampleService(UseWSDL: Boolean = System.False; Addr: string = ' '; HTTPRIO: THTTPRIO = nil): ISampleService;
implementation
function GetISampleService(UseWSDL: Boolean ; Addr: string ; HTTPRIO: THTTPRIO): ISampleService;
const
defWSDL = ' http://localhost/MyServices/SampleService/libss.dll/wsdl/ISampleService';
defURL = ' http://localhost/MyServices/SampleService/libss.dll/soap/ISampleService';
defSvc = ' ISampleServiceservice';
defPrt = ' ISampleServicePort';
var
RIO: THTTPRIO;
begin
Result : = nil;
if (Addr = ' ') then
begin
if UseWSDL then
Addr : = defWSDL
else
Addr : = defURL;
end ;
if HTTPRIO = nil then
RIO : = THTTPRIO.Create(nil)
else
RIO : = HTTPRIO;
try
Result : = (RIO as ISampleService);
if UseWSDL then
begin
RIO.WSDLLocation : = Addr;
RIO.Service : = defSvc;
RIO.Port : = defPrt;
end else
RIO.URL : = Addr;
finally
if (Result = nil) and (HTTPRIO = nil) then
RIO.Free;
end ;
end ;
destructor TLoopable.Destroy;
begin
if Assigned(FData) then
FData.Free;
if Assigned(FNext) then
FNext.Free;
inherited Destroy;
end ;
destructor TClassA.Destroy;
begin
if Assigned(Fref) then
Fref.Free;
inherited Destroy;
end ;
destructor TClassB.Destroy;
begin
if Assigned(Fref) then
Fref.Free;
inherited Destroy;
end ;
initialization
InvRegistry.RegisterInterface(TypeInfo(ISampleService), ' urn:SampleServiceIntf-ISampleService', 'utf-8');
InvRegistry.RegisterDefaultSOAPAction(TypeInfo(ISampleService), ' urn:SampleServiceIntf-ISampleService#%operationName%');
RemClassRegistry.RegisterXSClass(TComplex, ' urn:SampleServiceIntf', 'TComplex');
RemClassRegistry.RegisterXSClass(TExtraData, ' urn:SampleServiceIntf', 'TExtraData');
RemClassRegistry.RegisterXSClass(TLoopable, ' urn:SampleServiceIntf', 'TLoopable');
RemClassRegistry.RegisterXSClass(TClassA, ' urn:SampleServiceIntf', 'TClassA');
RemClassRegistry.RegisterXSClass(TClassB, ' urn:SampleServiceIntf', 'TClassB');
end .
注意上面的destructors!
把TClassB.Destroy改成这样:
destructor TClassB.Destroy;
begin
inherited Destroy;
end ;
begin
inherited Destroy;
end ;
好了,接下来可以开始编写program的内容了。导入之后,用法非常简单,下面是最终编写完的程序。
program SampleService.Invoker;
{$APPTYPE CONSOLE}
uses
SysUtils,
Forms,
ISampleServiceUnit in ' ISampleServiceUnit.pas ' ;
var
service:ISampleService;
a,b,x:TComplex;
p,q:TLoopable;
ca:TClassA;
begin
Application.Initialize; // use this method to initial COM
service: = GetISampleService;
// ComplexAdd
a: = TComplex.Create;
a.R: = 1 ;
a.I: = 2 ;
b: = TComplex.Create;
b.R: = 3 ;
b.I: = 4 ;
try
x: = service.ComplexAdd(a,b);
Writeln(x.R, ' + ' ,x.I, ' i ' );
finally
a.Free;
b.Free;
end;
// Loop
p: = service.Loop( 5 );
q: = p;
while p <> nil do
begin
if p.Data <> nil then
begin
Writeln(p.Data.X);
// p.Data.Free; <-- do not free it first
end
else Writeln( ' nil ' );
p: = p.Next;
end;
q.Free; // Please read the destructors in unit ISampleServiceUnit
// ClassAB
ca: = service.GetClassAB;
if ca. ref . ref = ca then
Writeln( ' true ' )
else Writeln( ' false ' );
ca.Free; // <-- pay attention to it!
Readln;
end.
{$APPTYPE CONSOLE}
uses
SysUtils,
Forms,
ISampleServiceUnit in ' ISampleServiceUnit.pas ' ;
var
service:ISampleService;
a,b,x:TComplex;
p,q:TLoopable;
ca:TClassA;
begin
Application.Initialize; // use this method to initial COM
service: = GetISampleService;
// ComplexAdd
a: = TComplex.Create;
a.R: = 1 ;
a.I: = 2 ;
b: = TComplex.Create;
b.R: = 3 ;
b.I: = 4 ;
try
x: = service.ComplexAdd(a,b);
Writeln(x.R, ' + ' ,x.I, ' i ' );
finally
a.Free;
b.Free;
end;
// Loop
p: = service.Loop( 5 );
q: = p;
while p <> nil do
begin
if p.Data <> nil then
begin
Writeln(p.Data.X);
// p.Data.Free; <-- do not free it first
end
else Writeln( ' nil ' );
p: = p.Next;
end;
q.Free; // Please read the destructors in unit ISampleServiceUnit
// ClassAB
ca: = service.GetClassAB;
if ca. ref . ref = ca then
Writeln( ' true ' )
else Writeln( ' false ' );
ca.Free; // <-- pay attention to it!
Readln;
end.