【问题标题】:How does Delphi web-services work ? ( Adding method in runtime ?? )Delphi 网络服务是如何工作的? (在运行时添加方法??)
【发布时间】:2011-04-05 08:38:25
【问题描述】:

我使用 WSDL 导入器在 Delphi XE 中创建了 Web 服务。 Delphi 为我生成了模块 ITransmitter1.pas ITransmitter 接口和 GetITransmitter 函数。

要使用我使用的网络服务:

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 正在 RunTime 中添加方法! 它是如何工作的 ?我可以在运行时将方法添加到我自己的类中吗?

【问题讨论】:

    标签: web-services delphi interface runtime


    【解决方案1】:

    如果您使用 WSDL 导入器创建了 Web 服务客户端,则生成的客户端代码将调用服务器上的方法。所以事实上,方法'body'(代码)是在web服务服务器上的。

    Delphi 基于 WSDL 生成 Soap 请求,并在后台使用 RTTI(自省)将 Web 服务调用的参数等生成为 XML。这个 XML 被发送到服务器,服务器执行方法实现并返回一个 Soap 响应。

    如果创建 Web 服务服务器,情况则相反,在这种情况下,Delphi 应用程序当然需要实现所有方法体。

    【讨论】:

    • 我无法调试我的 Transmitter.Transmit 方法。而且我仍然想知道当我调用 Transmitter.Transmit 时实际上执行了哪个方法?通常当我调用一些方法时,我会看到一些 .pas 文件中的代码。现在我不知道当我调用这个方法时实际发生了什么......
    【解决方案2】:

    实际上,您调用的是在接口中定义的方法,而该接口又继承自在 System.pas 中声明的 IInvokable。

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

    在此之前,有一些帕斯卡代码用于创建一个适当的 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);结果 := (RIO 作为 ITransmitter);所以 Transmit 方法的实现应该在 THTTPRIO 类中。但正如我所见,没有一个。因此,据我所知,无论何时调用 Transmitter 的任何方法,实际上 TRIO.GenericStub 都会被执行。那么我可以用这个未来自己上课吗?我就是这样的类,所以不管我调用哪个方法,反正delphi会调用一些固定的方法?
    • @Astronavigator:ITransmitter 是Delphi 在WDSL 导入器处理WDSL 时生成的接口。简而言之,您调用的任何接口方法都会调用通用方法。没有在客户端定义该方法的实际对象:定义接口是为了您的方便,您可以与 Web 服务进行交互,就像您在应用程序中与其他对象进行交互一样。 THTTPRio/TRio 类使用标准 QueryInterface 方法,该方法在 AS 操作员将对象强制转换为 Interface 以动态生成 VTable 以执行该映射时调用。
    • 查看 TRio.GenVTable 方法,该方法在处理 QueryInterface 时调用。单位是soap\Rio.pas
    猜你喜欢
    • 1970-01-01
    • 2019-10-27
    • 1970-01-01
    • 1970-01-01
    • 2023-03-07
    • 2011-02-01
    • 1970-01-01
    • 1970-01-01
    • 2020-04-15
    相关资源
    最近更新 更多