Я использую Delphi XE2 для связи с довольно большой службой SOAP. Я успешно импортировал wsdl, и все работает нормально. Тем не менее, я обнаружил, что пишу много подобного кода. Я хотел бы иметь общий метод, который вызывает мой веб-сервис. Мне также трудно использовать многопоточность в моем коде, как сейчас, поскольку мне приходится писать так много кода для каждого типа вызова.
Будучи больше программистом выходного дня, я далек от того, чтобы освоить все тонкости Delphi, но я думаю, что у меня, по крайней мере, есть хорошее понимание RTTI, которое, я считаю, должно использоваться для того, чтобы делать то, что я хочу.
Веб-сервис имеет около 700 различных методов, и это большая проблема. Код, сгенерированный из wsdl, имеет следующие методы:
function addPhone(const Params: addPhone): addPhoneResponse; stdcall;
function updatePhone(const Params: updatePhone): updatePhoneResponse; stdcall;
function getPhone(const Params: getPhone): getPhoneResponse; stdcall;
function removePhone(const Params: removePhone): removePhoneResponse; stdcall;
function listPhone(const Params: listPhone): listPhoneResponse; stdcall;
function addStuff(const Params: addStuff): addStuffResponse; stdcall;
function updateStuff(const Params: updateStuff): updateStuffResponse; stdcall;
...
... about 700 more of the above
В основном,существует около 700 различных типов вещей, которые можно обрабатывать, и для всех них есть методы добавления, обновления, получения, удаления и перечисления -. При каждом вызове имеется соответствующий класс, который используется в качестве параметров запроса SOAP. Существует также соответствующий класс для ответа, как вы можете видеть выше.
Классы будут выглядеть примерно так (очень упрощенно):
addStuff = class
private
FStuff: string;
published
property stuff: string Index (IS_UNQL) read FStuff write FStuff;
end;
Поэтому, когда я вызываю веб-службу, я, например, делаю:
procedure CreateStuff;
var
req: addStuff;
res: addStuffResponse;
soap: MyWebServicePort;
begin
// Use the function in the wsdl-generated code to create HTTPRIO
soap := GetMyWebServicePort(false,'',nil);
// Create Parameter Object
req := addPhone.Create;
req.stuff := 'test';
// Send the SOAP Request
res := soap.addStuff(req);
end;
(Да, я знаю, я должен был попробовать.. наконец, и Свободный там тоже:-))
Затем где-то еще в коде мне нужно вызвать другой метод:
procedure listStuff;
var
req: listStuff;
res: listStuffResponse;
soap: MyWebServicePort;
begin
// Use the function in the wsdl-generated code to create HTTPRIO
soap := GetMyWebServicePort(false,'',nil);
// Create Parameter Object
req := listPhone.Create;
req.stuff := 'test2';
// Send the SOAP Request
res := soap.listStuff(req);
end;
Поскольку я знаю, что параметр всегда является классом с именем, эквивалентным вызываемому мной методу, я хотел бы иметь возможность сделать что-то вроде приведенного ниже метакода для динамического вызова вызова. Я предполагаю, что это требует некоторой магии RTTI, но я не смог найти способ сделать это:
procedure soapRequest(Param: Something; var Response: Something);
begin
soap := GetMyWebServicePort(false,'',nil);
Response := soap.DynamicInvoke(Param.ClassName, Param);
end
Тогда я мог бы сделать что-то вроде:
soapRequest(VarOfTypeAddStuff,VarOfTypeAddStuffResponse)
soapRequest(VarOfTypeListStuff,VarOfTypeListStuffResponse)
...
Кто-нибудь знает, как можно упростить мои звонки в веб-сервис?