加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 大数据 > 正文

delphi – 按名称动态调用SOAP方法?

发布时间:2020-12-15 10:08:09 所属栏目:大数据 来源:网络整理
导读:这是我在这个论坛上的第一篇文章,希望能以正确的方式提出我的问题.对不起长度,但是我觉得很难把它砍下来. 我正在使用Delphi XE2与一个相当大的SOAP服务进行通信.我已成功导入wsdl,一切都正常工作.但是,我发现自己写了很多类似的代码.我想要一个通用的方法来
这是我在这个论坛上的第一篇文章,希望能以正确的方式提出我的问题.对不起长度,但是我觉得很难把它砍下来.

我正在使用Delphi XE2与一个相当大的SOAP服务进行通信.我已成功导入wsdl,一切都正常工作.但是,我发现自己写了很多类似的代码.我想要一个通用的方法来调用我的Web服务.我也很难多次读取我的代码,因为我现在必须为每种类型的调用写入这么多的代码.

更多的是一个周末的程序员,我远远不能掌握德尔福的进出口,但我认为至少对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种不同类型的东西可以被处理,并且有它们的添加,更新,获取,删除和列表方法.对于每个调用,都有一个对应的类用作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;

因为我知道这个参数总是一个类,它的名字等同于我所调用的方法,所以我想要像下面的metacode那样做一些动态的调用.我想这需要一些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)
...

有没有人有一个想法如何可以简化我对网络服务的呼叫?

提前致谢

解决方法

真的很奇怪,我刚刚发布一个问题,我一直在努力解决自己几个星期,突然之间刚刚解决了自己…我的灵感来自于周围的SO,我发现这个一路帮助我: Delphi – Invoke Record method per name.

我的方案我有点具体,因为我使用与方法本身具有相同类名称的参数来调用方法.我也写了一个更简单的版本,与公共Web服务进行通信.如果有人有兴趣,您可以在这里获得代码:http://www.hook.se/delphi/SoapDynamicInvoke.zip.这是一个无用的例子,因为执行动态方法调用仅在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;

有一些打字必要,但在我的情况下,我觉得我会很安全的.有人有任何其他意见/建议吗?我的意思是说,这有用,但可能有办法加强它.

干杯,

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读