Ich verwende Delphi XE2, um mit einem ziemlich großen SOAP-Dienst zu kommunizieren. Ich habe erfolgreich die WSDL importiert und alles funktioniert gut. Ich finde jedoch, dass ich viel ähnlichen Code schreibe. Ich möchte eine generische Methode haben, die meinen Webservice aufruft. Ich finde es auch schwierig, meinen Code so zu multithread wie es jetzt ist, da ich so viel Code für jede Art von Anruf schreiben muss.Dynamische Aufrufen einer SOAP-Methode nach Name?
Da ich eher ein Wochenendprogrammierer bin, bin ich weit davon entfernt, die Delphi zu beherrschen, aber ich denke zumindest, dass ich RTTI gut verstehe, was meiner Meinung nach dazu dienen muss, das zu tun, was ich will.
Der Web-Service hat etwa 700 verschiedene Methoden und das ist so ziemlich das Problem. Der Code erzeugt aus der WSDL-Datei verfügt über Methoden wie folgt:
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
Grundsätzlich gibt es etwa 700 verschiedene Arten von Dingen, die behandelt werden können, und es gibt hinzufügen, aktualisieren, entfernen und list-Methoden für sie alle . Bei jedem Aufruf gibt es eine entsprechende Klasse, die als Parameter für die SOAP-Anfrage verwendet wird. Es gibt auch eine entsprechende Klasse für die Antwort, wie Sie oben sehen können.
Die Klassen würden in etwa so aussehen (sehr vereinfacht):
addStuff = class
private
FStuff: string;
published
property stuff: string Index (IS_UNQL) read FStuff write FStuff;
end;
Also, wenn ich rufe den Webdienst ich zum Beispiel so tun:
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;
(Ja, ich weiß, ich versuche haben sollte ..finally und Free da drin auch :-))
Dann woanders im Code muss ich eine andere Methode aufrufen:
Da ich weiß, dass der Parameter immer eine Klasse mit einem Namen ist, der der Methode entspricht, die ich anrufe, möchte ich in der Lage sein, etwas wie den Metacode unten zu tun, um den Aufruf dynamisch aufzurufen. Ich denke, es etwas RTTI Magie erfordert aber ich have'nt einen Weg zu finden, in der Lage, es zu tun:
procedure soapRequest(Param: Something; var Response: Something);
begin
soap := GetMyWebServicePort(false,'',nil);
Response := soap.DynamicInvoke(Param.ClassName, Param);
end
Dann etwas wie ich tun konnte:
soapRequest(VarOfTypeAddStuff,VarOfTypeAddStuffResponse)
soapRequest(VarOfTypeListStuff,VarOfTypeListStuffResponse)
...
Hat jemand eine Idee, wie meine Anrufe zum Webservice können vereinfacht werden?
Es wird interessant sein zu sehen, ob jemand mit einer solchen kommt, aber ich schrieb nur Wrapper-Routinen, wie Sie die Details zu „verstecken“ haben. – mj2008
@dahook: Sehr schön geschriebener erster Beitrag. Abgestimmt. Willkommen bei SO. – RobertFrank