views:

459

answers:

3

Is there a robust mechanism for making a copy of TRemotable object (or descendant) in Delphi 2007?

I'm creating a Delphi web service client that receives a variety of objects from a web service; of course, all are descendants of TRemotable. In the client, I create a matching object, then copy all the properties from the web service provided TRemotable to my own object. This is done via TypInfo.GetPropList() and then a loop around TypInfo. GetPropValue() and TypInfo.SetPropValue() method calls. Although this works great for the simple types - strings, ints, bool, etc, it doesn't work for complex types, like dates, times or sub-object types. And I assume that if the web service ever makes use of a new complex type, my copy code would also break.

It looks like one possibility is to serialize the object out to an XML document, then read it into the new object. But this seems like a great deal of overhead to just copy a series of properties around.

A: 

TDateTime is just a Double by a different name, and you ought to be able to copy it without trouble. Or are you using some other format for your dates and times?

As for sub-objects, they can be handled by making your copy routine recursive. If it comes across a property that's an object, have it make a copy of that object and assign it to the parent object. (NOTE: This will only work if the sub-object also has published properties.)

Mason Wheeler
TDateTime is a double in native Delphi code. But not when it's a TRemotable property; in that case, it's a TXSDateTime. It looks like my copy code is breaking on any of the TXS... types.
Jason Swager
A: 

Yes you could make the copy recursive, but that still leaves you with problems, how to copy internal private fields. You would have to expose all fields as properties and in my opinion that is not clean and is cumbersome.

I would definitely serialize the object. SOAP has so much overhead on its own that serialization is super fast in comparison. I would even argue that a simple HTTP approach using REST would be better.

You can look at my SimpleStorage framework that was made with such tasks (serialization) in mind. Especially look at adapters feature.

You can get it at: http://www.cromis.net/blog/downloads/

There are also articles there that show how to use it. If you are already using other XML library and don't want to switch I would still prefer the serialization approach if I were you.

I doubt that you can make a http request last under 30ms. Serialization would take way less than that. Now add the SOAP overhead and you are super fast compared to it :)

Runner
I'm not worried about private properties. These TRemotable-descendant objects are built by WSDLImp.exe and have nothing but published properties. And if I do create my own descendants of those objects with my own private properties, the only properties I would be interested in copying would be the original published ones.
Jason Swager
The HTTP+REST approach doesn't work either; the web services is outside my control and SOAP is the only approach.
Jason Swager
Ok, I see you found a solution that works for you. I did not know that SOAP was obligatory
Runner
A: 

Found a more robust solution, seems to work fine for simply types, TXS... derivative types and subobject types:

procedure CopyNormal(Source, Target: TRemotable);
var
  Converter: IObjConverter;
  NodeObject: IXMLNode;
  NodeParent: IXMLNode;
  NodeRoot: IXMLNode;
  XML: IXMLDocument;
  XMLStr: WideString;
begin
  XML:= NewXMLDocument;
  NodeRoot:= XML.AddChild('Root');
  NodeParent:= NodeRoot.AddChild('Parent');
  Converter:= TSOAPDomConv.Create(NIL);
  NodeObject:= Source.ObjectToSOAP(NodeRoot, NodeParent, Converter, 'CopyObject', '', [ocoDontPrefixNode], XMLStr);
  Target.SOAPToObject(NodeRoot, NodeObject, Converter);
end;
Jason Swager