
这是我在该论坛上的第一篇文章,我希望以正确的方式提出我的问题. 抱歉,长度不够,但是我发现很难缩减长度.
我正在使用Delphi XE2与相当大的SOAP服务进行通信. 我已经成功导入了wsdl,并且一切正常. 但是,我发现自己写了很多类似的代码. 我想要一个通用方法来调用我的Web服务. 我也很难多次读取代码,因为现在我必须为每种类型的调用编写大量代码.
更多的是周末程序员,我远远不掌握Delphi的导入和导出,但是我认为至少我对RTTI有很好的了解,我相信我应该习惯于做自己想做的事情.
p>
大约有700种不同的Web服务方法,这几乎是一个问题. 从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

基本上delphi中soap协议下载文件,可以处理大约700种不同类型的事物,包括添加,更新,获取,删除和列出方法. 对于每个调用,都有一个对应的类用作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;
(是的,我知道我应该尝试,它是完全免费的,并且: -))

因此,在代码的其他地方,我需要调用其他方法:
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;
因为我知道此参数始终是一个类,所以它的名称等效于我调用的方法delphi中soap协议下载文件,因此我想进行一些动态调用,例如下面的元代码. 我认为这需要一些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) ...

有人知道如何简化对网络服务的呼叫吗?
预先感谢
Tan
这真的很奇怪. 我刚发布了一个问题. 我已经为自己工作了几周,突然间我就解决了自己……我受到周围SO的启发. 我发现这对我有帮助:
我的方案有点具体,因为我使用与方法本身具有相同类名的参数来调用该方法. 我还编写了一个更简单的版本来与公共Web服务进行通信. 如果有人感兴趣,您可以在此处获取代码: 这是一个无用的示例,因为仅当Web服务具有许多不同的方法时才执行动态方法调用. 但是,可能会有人感兴趣: -)
这是我解决网络服务的方式. 如上所述,这是非常具体的,并且代码可以更通用,但这对我有用.

使用TRemotable对象调用此方法,然后使用与对象的类名相同的方法调用Web服务.
function soapRequest(Param: TRemotable): TValue;
var
soap: AXLPort;
C: TRttiContext;
T: TRttiType;
M: TRttiMethod;
SoapParam: TArray<TValue>;
TVres: TValue;
soap: MyWebServicePort;
begin
// Use the function in the wsdl-generated code to create HTTPRIO
soap := GetMyWebServicePort(false,'',nil); C := TRttiContext.Create;
T := C.FindType('MyWebService.MyWebServicePort');
M := T.GetMethod(Param.ClassName);
SetLength(SoapParam,1);
SoapParam[0] := TValue.From(Param);
TVres := M.Invoke(TValue.From<IInterface>(soap), SoapParam);
Result := TVres;
end;
并使用以上功能:
procedure DoSomeSoapCalls(Sender: TObject);
var
req1: getStuff
res1: getStuffResponse;
req2: addStuff;
res2: addStuffResponse;
res: TValue;
begin
//Request #1
req1 := getStuff.Create;
req1.stuffToGet := 'abc';
try
res := soapRequest(req1);
res1 := getStuffResponse(res.AsObject);
finally
req1.Free;
end;
Writeln(res1.someproperty);
FreeAndNil(res1);
//Request #2
req2 := addStuff.Create;
req2.StuffToAdd := 'cde';
try
res := soapRequest(req2);
res2 := addStuffResponse(res.AsObject);
finally
req2.Free;
end;
Writeln(res2.result);
FreeAndNil(res2);
end;
我有一些打字,但就我而言,我认为我会安全的. 有人还有其他意见/建议吗?我的意思是,这可行,但是可能有一些方法可以加强它.
干杯
Tan
本文来自电脑杂谈,转载请注明本文网址:
https://www.pc-fly.com/a/jisuanjixue/article-162075-1.html
哈哈