Delphi Web服务是如何工作的?(在运行时添加方法?)

3

我使用WSDL导入程序在Delphi XE中创建了一个Web服务。Delphi为我生成了ITransmitter1.pas模块,其中包含ITransmitter接口和GetITransmitter函数。

要使用Web服务,我使用:

var Transmitter: ITransmitter;
begin
  Transmitter := GetITransmitter(True, '', nil);
  Transmitter.Transmit(Memo1.Text, OutXML);
end;

但是我无法在 Transmit 方法的任何地方看到函数体...

在 ITransmitter.pas 文件中,我看到:

  InvRegistry.RegisterInterface(TypeInfo(ITransmitter), 'urn:TransmitterIntf-ITransmitter', 'utf-8');
  InvRegistry.RegisterDefaultSOAPAction(TypeInfo(ITransmitter), 'urn:TransmitterIntf-ITransmitter#Transmit');

如果我注释掉这些行,就会出现“接口不支持”的错误。 从这里看来,Delphi在运行时添加了方法! 这是如何实现的?我能否在运行时向我的类中添加方法?
2个回答

2
如果您使用WSDL导入程序创建Web服务客户端,则生成的客户端代码将在服务器上调用一个方法。因此,实际上,方法“主体”(代码)位于Web服务服务器上。
Delphi基于WSDL生成Soap请求,并且在幕后使用RTTI(内省)生成Web服务调用的参数等作为XML。该XML被发送到服务器,服务器执行方法实现并发送回Soap响应。
如果您创建Web服务服务器,则情况相反,在这种情况下,Delphi应用程序当然需要实现所有方法主体。

我无法调试我的Transmitter.Transmit方法。 我仍然想知道当我调用Transmitter.Transmit时实际执行的方法是哪个?通常,当我调用某个方法时,我会看到在某个.pas文件中放置的代码。现在,我不知道调用此方法时实际发生了什么... - Astronavigator

1

实际上,你正在调用一个在接口中定义的方法,该接口继承自System.pas中声明的IInvokable。

如果你检查源代码,你会发现在你的项目中没有任何本地对象实现了你正在调用的IInvokable接口,这是因为该方法在服务器上远程执行。

在此之前,有一些Pascal代码用于创建一个适当的SOAP请求并将其发送到服务器,然后等待和解释服务器响应。请考虑这些实现细节。如果你想了解更多关于它是如何工作的,请启用“使用调试.Dcus”编译器选项,这样你就可以在VCL/RTL内部进行调试。

然后,像往常一样,使用StepInto(F7)命令来要求调试器逐步执行Transmit方法...经过TRIO.GenericStub方法中的一些汇编代码后,你将进入TRIO.Generic方法,在那里准备并发送数据包。

对于我用来撰写这篇回答的btSOAP绑定,相关部分从Rio.pas单元的第943行开始:

    try
      FWebNode.Execute(Req, Resp);
    finally
      { Clear Outbound headers }
      FHeadersOutBound.Clear;
    end;          

THTTPReqResp.Execute 然后使用 wininet.dll 函数来执行连接、发送和接收信息与服务器。

这个可以深入探索一些层面......你想要走多远,将取决于你的兴趣和大量细节远远超出了我的回答范围......请随意发布更多关于你感兴趣的具体内容的问题。

我不确定,但是细节可能会因 Delphi 版本而变化......我现在正在使用 Delphi XE。


好的。我看到的是:Transmitter对象是通过GetITTransmitter函数生成的。该函数以以下方式生成结果:RIO:= THTTPRIO.Create(nil); Result: =(RIO as ITransmitter); 因此,Transmit方法的实现应在THTTPRIO类中。但是,我发现没有一个。因此,我理解每当我调用Transmitter的任何方法时,无论哪个方法,实际上都将执行TRIO.GenericStub。那么我能否制作自己的具有此功能的类?我的意思是这样的类,因此无论我调用哪个方法,Delphi都会调用某个固定的方法? - Astronavigator
@Astronavigator:ITransmitter是由Delphi在处理WDSL导入器时生成的接口。简而言之,通用方法会被调用以处理您调用的任何接口方法。在客户端没有实际对象定义该方法:接口是为您方便定义的,您可以像与应用程序中的其他对象一样与Web服务进行交互。THTTPRio/TRio类使用标准QueryInterface方法,而AS运算符将对象强制转换为接口以生成一个VTable来执行该映射。 - jachguate
请查看TRio.GenVTable方法,该方法在处理QueryInterface时被调用。该单元是soap\Rio.pas。 - jachguate

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接