I was wondering, is there anything in the RTTI of Delphi that will do the same as MemberwiseClone does in C# for the simple implementation of the prototype pattern. I saw so
I think you are looking for something similar to this: http://code.google.com/p/delphilhlplib/source/browse/trunk/Library/src/Extensions/DeHL.Cloning.pas
It will only work on D2010 and up (requires extended RTTI).
I posted a somewhat generic component cloning answer a while back that might be useful, although it's not the equivalent of MemberWiseClone
. It works in Delphi as far back as D5, I believe, and I'm sure it works in D2007.
There's nothing built in that will perform a deep-clone for you. I'm sure you could write a deep-clone based on the new RTTI, but I'd expect it to be a non-trivial amount of work.
If you were dealing with simple enough types it would work fine, but you could easily run into serious challenges. For example, off the top of my head:
You could implement your prototype pattern by defining a basic Clone()
method which uses RTTI for simple types and then you have to override it for anything more complex. Personally though, I'd inherit from TPersistent
and make my Clone()
method based on Assign
.
There’s a way to perform a deep-copy (clone) of an object in Delphi. It works for the latest versions of Delphi (2010 and above). See the code snipped below...it’s actually quite simple and you don't need external libraries. You can find more information here: http://www.yanniel.info/2012/02/deep-copy-clone-object-delphi.html
function DeepCopy(aValue: TObject): TObject;
var
MarshalObj: TJSONMarshal;
UnMarshalObj: TJSONUnMarshal;
JSONValue: TJSONValue;
begin
Result:= nil;
MarshalObj := TJSONMarshal.Create;
UnMarshalObj := TJSONUnMarshal.Create;
try
JSONValue := MarshalObj.Marshal(aValue);
try
if Assigned(JSONValue) then
Result:= UnMarshalObj.Unmarshal(JSONValue);
finally
JSONValue.Free;
end;
finally
MarshalObj.Free;
UnMarshalObj.Free;
end;
end;
Object.MemberwiseClone Method makes a shallow copy of the object following some very simple rules and taking advantage of how the .NET garbage collector works.
object
.The part about the value types can easily be duplicated with Delphi. Duplicating the reference-type behavior with Delphi, while technically easy, will not provide the expected result: Delphi code is expected to .free
the objects it creates, and it uses a owner-owned
paradigm to make sure that happens. The usual pattern is to free objects created by the owner-object from the destructor. If you make a shalow-copy of the object, this results in failure. Here's an example:
A.Free;
B.Free;
- this automatically calls B.Free
, but unfortunately B was already freed when we freed A!We could attempt a deep-copy
, as David suggests, but that poses some equally difficult problems:
Application
?Putting this all together we can only reach one conclusion: We can't have a general purpose, Delphi equivalent of MemberwiseClone
. We can have a partial look-alike for simpler objects with uncomplicated interactions, but that's not nearly as appealing!