title: Dynamically Invoking a SOAP method by name?
body: <p>I am using Delphi XE2 to communicate with a fairly large SOAP service. I've successfully imported the wsdl and everything is working just fine. However, I find myself writing a lot of similar code. I would like to have a generic method that calls my web service. I also find it hard to multithread my code as it is now, since I have to write so much code for each type of call.</p>
  
  <p>Being more of a weekend programmer I am far from mastering the in and outs of Delphi, but I think I at least have a fair understanding of RTTI, which I believe must be used to do what I want.</p>
  
  <p>The web service has about 700 different methods and that is pretty much the problem. The code generated from the wsdl has methods as below:</p>
  
  <pre><code>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
  </code></pre>
  
  <p>Basically, there is about 700 different type of things that can be handled, and there is add,update,get,remove and list-methods for them all. With each call, there is a corresponding class that is used as parameters to the SOAP request. There is also a corresponding class for the response as you can see above.</p>
  
  <p>The classes would look something like (very simplified):</p>
  
  <pre><code>addStuff = class
    private
      FStuff: string;
    published
      property stuff: string  Index (IS_UNQL) read FStuff write FStuff;
    end;
  </code></pre>
  
  <p>So when I call the web service I do for example:</p>
  
  <pre><code>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;
  </code></pre>
  
  <p>(Yes, I know I should have try..finally and Free in there as well :-) )</p>
  
  <p>Then, somewhere else in the code I need to call a different method:</p>
  
  <pre><code>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;
  </code></pre>
  
  <p>Since I know that the parameter is always a class with a name that is equivalent of the method I call, I would like to be able to do something like the metacode below in order to dynamically invoking the call. I guess it requires some RTTI magic but I have'nt been able to find a way to do it:</p>
  
  <pre><code>procedure soapRequest(Param: Something; var Response: Something);
  begin
    soap := GetMyWebServicePort(false,'',nil);
    Response := soap.DynamicInvoke(Param.ClassName, Param);
  end
  </code></pre>
  
  <p>Then I could do something like:</p>
  
  <pre><code>soapRequest(VarOfTypeAddStuff,VarOfTypeAddStuffResponse)
  soapRequest(VarOfTypeListStuff,VarOfTypeListStuffResponse)
  ...
  </code></pre>
  
  <p>Does anyone have an idea how my calls to the webservice can be simplified?</p>