用Delphi编写Web Service(实例)

1. File->New->Other,在打开的对话框中,选择Web Services/SOAP Server Application。

2. 在这里选择ISAPI DLL。

3. 问咱Create Interface for SOAP module,当然是yes啦,然后输入个名称XXX,等下会生成XXXIntf.pas和XXXImple.pas这两个文件,分别对应接口和类的实现。在这里,对外公布的都是接口。

Service name: SampleService

如果这里不添加,也可以使用SOAP Server Interface向导来添加接口。

最后编译生成的叫libss.dll。

这里最主要关注的是SampleServiceIntf.pas和SampleServiceImpl.pas。

SampleServiceIntf.pas

{ Invokable  interface  ISampleService }

unit SampleServiceIntf;

interface

uses InvokeRegistry, Types, XSBuiltIns;

type

  { Invokable interfaces must derive from IInvokable }
  ISampleService 
=   interface (IInvokable)
  [
' {C003A413-B302-437C-990C-1ADFAA03A619} ' ]

    { Methods of Invokable 
interface  must not use the  default  }
    { calling convention; stdcall 
is  recommended }
  end;

implementation

initialization
  { Invokable interfaces must be registered }
  InvRegistry.RegisterInterface(TypeInfo(ISampleService));

end.

SampleServiceImpl.pas

{ Invokable implementation File  for  TSampleService which  implements  ISampleService }

unit SampleServiceImpl;

interface

uses InvokeRegistry, Types, XSBuiltIns, SampleServiceIntf;

type

  { TSampleService }
  TSampleService 
=   class (TInvokableClass, ISampleService)
  
public
  
end ;

implementation


initialization
{ Invokable classes must be registered }
   InvRegistry.RegisterInvokableClass(TSampleService);
end .

 

要公布的接口必须继承IInvokable

        IInvokable其实跟IInterface是一样的,不同之处在于带上了{$M}编译指令,使用这个编译指令,使得它以及它的子类都具有RTTI。

{$M + }
  IInvokable 
=   interface (IInterface)
  
end ;
{$M
- }

 

要用于数据传递的类必须继承TRemotable

        要用于数据传递的类必须继承TRemotable,并且必须在published中以property的形式公布数据。对于复杂的类引用(包括递归引用),也是没问题的。可是,如果在结果的地方返回一个对象,它将会在什么时候被销毁呢?会不会造成内存泄漏呢?看看TRemotable.Create的源代码就知道了。 

constructor TRemotable.Create;
begin
  inherited;
  
if  RemotableDataContext  <>  nil  then
  begin
    TDataContext(RemotableDataContext).AddObjectToDestroy(Self);
    Self.DataContext :
=  TDataContext(RemotableDataContext);
  
end ;
end ;

 修改后的代码

 下面是SampleServiceIntf和SampleServiceImpl这两个单元修改后的代码。

SampleServiceIntf.pas

{ Invokable  interface  ISampleService }

unit SampleServiceIntf;

interface

uses InvokeRegistry, Types, XSBuiltIns;

type

  
//  要用于传送数据的类必须继承TRemotable
  
//  要传送的数据必须在published中用property公开
  TComplex
= class (TRemotable)
  
private
    FI: real;
    FR: real;
    procedure SetI(
const  Value: real);
    procedure SetR(
const  Value: real);
  published
  published
    
property  R:real read FR  write  SetR;
    
property  I:real read FI  write  SetI;
  
end ;

  
//  复杂的数据
  TExtraData
= class (TRemotable)
  
private
    FX: 
Integer ;
    procedure SetX(
const  Value:  Integer );
  published
    
property  X: Integer  read FX  write  SetX;
  
end ;

  TLoopable
= class (TRemotable)
  
private
    FData: TExtraData;
    FNext: TLoopable;
    procedure SetData(
const  Value: TExtraData);
    procedure SetNext(
const  Value: TLoopable);
  published
  published
    
property  Data:TExtraData read FData  write  SetData;
    
property   Next :TLoopable read FNext  write  SetNext  default  nil;
  
end ;

  
//  递归引用
  TClassA
= class ;
  TClassB
= class (TRemotable)
  
private
    Fref: TClassA;
    procedure Setref(
const  Value: TClassA);
  published
    
property  ref:TClassA read Fref  write  Setref  default  nil;
  
end ;
  TClassA
= class (TRemotable)
  
private
    Fref: TClassB;
    procedure Setref(
const  Value: TClassB);
  published
    
property  ref:TClassB read Fref  write  Setref  default  nil;
  
end ;

  { Invokable interfaces must derive from IInvokable }
  ISampleService 
=   interface (IInvokable)
  [
' {C003A413-B302-437C-990C-1ADFAA03A619}']
     //  这里参数传递方法最好用stdcall
    
function  ComplexAdd(a,b:TComplex):TComplex;stdcall;
    
function   Loop (Level: Integer ):TLoopable;stdcall;
    
function  GetClassAB:TClassA;stdcall;
  
end ;

implementation

{ TComplex }

procedure TComplex.SetI(
const  Value: real);
begin
  FI :
=  Value;
end ;

procedure TComplex.SetR(
const  Value: real);
begin
  FR :
=  Value;
end ;

{ TExtraData }

procedure TExtraData.SetX(
const  Value:  Integer );
begin
  FX :
=  Value;
end ;

{ TLoopable }

procedure TLoopable.SetData(
const  Value: TExtraData);
begin
  FData :
=  Value;
end ;

procedure TLoopable.SetNext(
const  Value: TLoopable);
begin
  FNext :
=  Value;
end ;

{ TClassA }

procedure TClassA.Setref(
const  Value: TClassB);
begin
  Fref :
=  Value;
end ;

{ TClassB }

procedure TClassB.Setref(
const  Value: TClassA);
begin
  Fref :
=  Value;
end ;

initialization
  { Invokable interfaces must be registered }
  InvRegistry.RegisterInterface(TypeInfo(ISampleService));

end .

 SampleServiceImpl.pas

{ Invokable implementation File  for  TSampleService which  implements  ISampleService }

unit SampleServiceImpl;

interface

uses InvokeRegistry, Types, XSBuiltIns, SampleServiceIntf;

type

  { TSampleService }
  TSampleService 
=   class (TInvokableClass, ISampleService)
  
public
    
function  ComplexAdd(a,b:TComplex):TComplex;stdcall;
    
function   Loop (Level: Integer ):TLoopable;stdcall;
    
function  GetClassAB:TClassA;stdcall;
  
end ;

implementation


{ TSampleService }

function  TSampleService.ComplexAdd(a, b: TComplex): TComplex;
begin
  Result:
= TComplex.Create;
  Result.R:
= a.R + b.R;
  Result.I:
= a.I + b.I;
  
//  可是这个对象,什么时候被销毁呢????
end ;

function  TSampleService.GetClassAB: TClassA;
begin
  Result:
= TClassA.Create;
  Result.ref:
= TClassB.Create;
  Result.ref.ref:
= Result;
  
//  这个对象能否被安全销毁呢?
end ;

function  TSampleService.Loop(Level:  Integer ): TLoopable;
var tmp:TLoopable;
    I:
Integer ;
begin
  Result:
= nil;
  
for  I : =   1   to  Level  do
    begin
      tmp:
= TLoopable.Create;
      tmp.Data:
= TExtraData.Create;
      tmp.Data.X:
= I;
      tmp.Next:
= Result;
      Result:
= tmp;
    
end ;
  
//  返回的对象将在什么时候被销毁呢????
end ;

initialization
{ Invokable classes must be registered }
   InvRegistry.RegisterInvokableClass(TSampleService);
end .

编译、部署

        ISAPI DLL的编译部署没啥好说的吧!?部署完了,可以用浏览器打开看到相应的定义。


 

编写客户端

        既然已经用delphi编写了server端,那么就用其它语言来编写个客户端来调用它。这里用vs2005 c#2.0。

首先,添加web referrence,这里是http://localhost/MyServices/SampleService/libss.dll/wsdl/ISampleService,引用名为SampleServiceRef。

代码如下:

 

using  System;
using  System.Collections.Generic;
using  System.Text;
using  SampleService.Invoker.CS.SampleServiceRef;

namespace  SampleService.Invoker.CS
{
    
class Program
    
{
        
static void Main(string[] args)
        
{
            
// ISampleServiceservice is a class
            ISampleServiceservice service = new ISampleServiceservice();

            
// ComplexAdd
            TComplex a = new TComplex();
            a.R 
= 1;
            a.I 
= 2;
            TComplex b 
= new TComplex();
            b.R 
= 3;
            b.I 
= 4;
            TComplex x 
= service.ComplexAdd(a, b);
            Console.WriteLine(
"{0} + {1}i", x.R, x.I);

            
// Loop
            TLoopable p = service.Loop(5);
            
while (p != null)
            
{
                
if (p.Data != null)
                    Console.WriteLine(p.Data.X);
                
else Console.WriteLine("null");
                p 
= p.Next;
            }


            
// GetClassAB
            TClassA ca = service.GetClassAB();
            
if (ca.@ref.@ref == ca) Console.WriteLine("true");
            
else Console.WriteLine("false");
        }

    }

}

 


附上自动生成的Reference.cs,仅供参考。

 

// ------------------------------------------------------------------------------
//  <auto-generated>
//      此代码由工具生成。
//      运行库版本:2.0.50727.42
//
//      对此文件的更改可能会导致不正确的行为,并且如果
//      重新生成代码,这些更改将会丢失。
//  </auto-generated>
// ------------------------------------------------------------------------------

//  
//  此源代码是由 Microsoft.VSDesigner 2.0.50727.42 版自动生成。
//  
#pragma  warning disable 1591

<
  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值