Как работают веб-службы Delphi ? ( Добавление метода во время выполнения ?? )

#web-services #delphi #interface #runtime

#веб-службы #delphi #интерфейс #время выполнения

Вопрос:

Я создал веб-службу в Delphi XE с помощью WSDL importer. 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 добавляет метод во время выполнения !
Как это работает? Могу ли я добавить метод во время выполнения в свой собственный класс?

Ответ №1:

Если вы создали клиент веб-службы с помощью импортера WSDL, сгенерированный клиентский код вызовет метод на сервере. Таким образом, фактически, «тело» метода (код) находится на сервере веб-службы.

Delphi генерирует Soap-запрос на основе WSDL, а за кулисами RTTI (самоанализ) используется для генерации параметров и т.д. вызова веб-службы в виде XML. Этот XML отправляется на сервер, который выполняет реализацию метода и отправляет обратно ответ Soap.

Все наоборот, если вы создаете сервер веб-службы, в этом случае приложение Delphi, конечно, должно реализовать все тела методов.

Комментарии:

1. Я не могу отладить свой передатчик. Метод передачи. И мне все еще интересно, какой метод на самом деле выполняется, когда я вызываю Transmitter. Передавать? Обычно, когда я вызываю какой-либо метод, я вижу код, помещенный в какой-нибудь файл .pas. Теперь я понятия не имею, что на самом деле происходит, когда я вызываю этот метод …

Ответ №2:

Фактически вы вызываете метод, определенный в интерфейсе, который, в свою очередь, наследуется от IInvokable, объявленного в System.pas.

Если вы проверите свой исходный код, вы заметите, что ни один локальный объект в вашем проекте не реализует вызываемый вами интерфейс IInvokable, это потому, что этот метод выполняется удаленно на сервере.

Прежде чем это произойдет, есть некоторый код pascal, используемый для создания надлежащего SOAP-запроса к серверу, отправки его, а затем ожидания и интерпретации ответа сервера, рассмотрим детали этой реализации. Если вам интересно узнать немного больше о том, как это работает, включите опцию компилятора «использовать debug .dcus», чтобы вы могли выполнять отладку внутри VCL / RTL.

Затем, как обычно, используйте команду StepInto (F7), чтобы попросить отладчик выполнить метод передачи шаг за шагом … после некоторого ассемблера в тройке.Методом GenericStub вы перейдете к ТРИО.Универсальный метод, при котором пакет подготавливается и отправляется.

Для привязки btSOAP, которую я использую для написания этого ответа, соответствующая часть начинается со строки 943 в блоке Rio.pas:

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

THTTPReqResp.Execute затем использует wininet.dll функции для выполнения соединения, отправки и получения информации с использованием сервера.

Есть несколько уровней, на которых вы можете углубиться в это… как далеко вы хотите зайти, будет зависеть от ваших интересов, а большое количество деталей выходит далеко за рамки моего ответа здесь … не стесняйтесь публиковать больше вопросов с конкретными интересующими вас вопросами.

Я не уверен, но детали могут меняться в зависимости от версий Delphi… Прямо сейчас я использую Delphi XE.

Комментарии:

1. ОК. Что я вижу: объект Transmitter был сгенерирован функцией GetITTransmitter. Эта функция генерирует результат следующим образом: RIO := THTTPRIO. Create(nil); Результат := (RIO как ITransmitter); Таким образом, повторная реализация метода Transmit должна быть в классе THTTPRIO. Но, как я вижу, такого нет. Итак, насколько я понимаю, всякий раз, когда я вызываю любой метод Transmitter, неважно, какой, на самом деле TRIO. Будет выполнен GenericStub. Итак, могу ли я создать свой собственный класс с этим future? Я имею в виду такой класс, поэтому независимо от того, какой метод я вызываю, в любом случае delphi вызовет какой-то фиксированный метод ?

2. @Astronavigator: ITransmitter — это интерфейс, сгенерированный Delphi при обработке WDSL импортером WDSL. Короче говоря, универсальный метод вызывается для любого вызываемого вами метода интерфейса. На стороне клиента нет реального объекта, в котором этот метод определен: интерфейс определен для вашего удобства, вы можете взаимодействовать с веб-службой так же, как и с другими объектами в вашем приложении. Классы THTTPRio / TRio используют стандартный метод QueryInterface, который вызывается, когда оператор AS приводит объект к интерфейсу, чтобы сгенерировать VTable «на лету» для выполнения этого сопоставления.

3. Взгляните на метод TRio.GenVTable, который вызывается при обработке QueryInterface. Модуль — soap Rio.pas