Delphi XE2 を使用して、かなり大規模な SOAP サービスと通信しています。wsdl のインポートに成功し、すべて正常に動作しています。しかし、私は自分が似たようなコードをたくさん書いていることに気づきました。Web サービスを呼び出す汎用メソッドが必要です。また、呼び出しの種類ごとに非常に多くのコードを書かなければならないため、現在のように自分のコードをマルチスレッド化するのは難しいと感じています。
週末のプログラマーなので、Delphi の内外をマスターするにはほど遠いですが、少なくとも RTTI についてはかなり理解していると思います。
Web サービスには約 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 種類あり、それらすべてに対して add、update、get、remove、および list メソッドがあります。各呼び出しには、SOAP 要求へのパラメーターとして使用される対応するクラスがあります。上記のように、応答に対応するクラスもあります。
クラスは次のようになります (非常に単純化されています)。
addStuff = class
private
FStuff: string;
published
property stuff: string Index (IS_UNQL) read FStuff write FStuff;
end;
したがって、Web サービスを呼び出すときは、たとえば次のようにします。
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;
(はい、try..finally とそこに Free もあるはずです :-) )
次に、コードの別の場所で別のメソッドを呼び出す必要があります。
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)
...
Web サービスへの呼び出しを簡素化する方法を知っている人はいますか?