Question

Je me demandais s'il y avait quelque chose dans le RTTI de Delphi qui ferait la même chose que MemberwiseClone en C# pour la simple implémentation du modèle de prototype.J'ai vu quelques implémentations Delphi de ce modèle dans lesquelles un nouvel objet est créé (TMyObject.Create) et ses propriétés sont affectées aux valeurs de l'objet de prototypage.Je me trompe peut-être, mais je ne vois pas l'avantage du modèle si nous, les objets, sommes créés de la même manière fondamentale.

Merci.

Était-ce utile?

La solution

Il n'y a rien de intégré qui puisse effectuer un clone profond pour vous.Je suis sûr que vous pourriez écrire un clone profond basé sur le nouveau RTTI, mais je m'attendrais à ce que ce soit une quantité de travail non négligeable.

Si vous aviez affaire à des types assez simples, cela fonctionnerait bien, mais vous pourriez facilement rencontrer de sérieux défis.Par exemple, ce qui me vient à l'esprit :

  • Certains groupes d'objets doivent être créés dans un ordre spécifique.
  • Certains membres d'une classe ne doivent pas être clonés, par ex.les références comptent.Comment reconnaître les personnes atteintes de RTTI ?
  • Comment gérez-vous les singletons ?
  • Qu’en est-il des références extrinsèques à mettre en place ?Supposons que vous clonez un objet normalement créé par une usine.Si cette usine contient une référence aux objets qu'elle crée, alors aller dans son dos peut casser votre conception.

Vous pouvez implémenter votre modèle de prototype en définissant un modèle de base Clone() méthode qui utilise RTTI pour les types simples et vous devez ensuite la remplacer pour quelque chose de plus complexe.Mais personnellement, j'hériterais de TPersistent et fais mon Clone() méthode basée sur Assign.

Autres conseils

Méthode Object.MemberwiseClone fait un peu profond copie de l'objet en suivant quelques règles très simples et en profitant du fonctionnement du garbage collector .NET.

  • Les références sont simplement copiées.Cela inclut les chaînes et les références à tout object.
  • Les types de valeur sont copiés en bits (des clones identiques sont créés).

La partie concernant les types valeur peut facilement être dupliquée avec Delphi.La duplication du comportement du type référence avec Delphi, bien que techniquement simple, ne fournira pas le résultat attendu :Le code Delphi devrait .free les objets qu'il crée, et il utilise un owner-owned paradigme pour garantir que cela se produise.Le modèle habituel consiste à libérer les objets créés par l'objet propriétaire du destructeur.Si vous faites une copie superficielle de l'objet, cela entraîne un échec.Voici un exemple :

  • L'objet A possède une référence à l'objet B.
  • Nous créons l'objet C comme une copie superficielle de l'objet A.L'objet C contient désormais une référence à l'objet B.
  • On libère l'objet A : A.Free;
  • On libère l'objet B : B.Free; - cela appelle automatiquement B.Free, mais malheureusement B était déjà libéré lorsque nous avons libéré A !

Nous pourrions tenter une deep-copy, comme le suggère David, mais cela pose des problèmes tout aussi difficiles :

  • Tous les objets ne doivent pas être copiés, par exemple parce qu'ils encapsulent des références à des ressources du monde réel (exemple :TFileStream).
  • Certains autres objets ne peuvent pas être copiés en profondeur car ils sont essentiellement des Singletons.Et il n'y a pas de moyen universel de dire "Cet objet est un Singleton, faites une simple copie de référence, ne faites pas de copie complète".Exemple:Est-ce qu'on copie Application?
  • Si vous effectuez une copie complète, vous pourriez avoir des références circulaires, vous devez en prendre soin.Ce n'est pas anodin, et si vous démarrez la copie à partir d'un élément d'une collection, vous risquez de vous retrouver au parent de votre collection, c'est à dire :pas exactement le résultat attendu.
  • Une adaptation approfondie aveugle peut occuper des quantités inattendues de mémoire et entraîner des fuites de mémoire inattendues.Pensez à nouveau à l'exemple collection -> élément -> copier l'élément, où vous vous retrouvez avec une copie de "l'élément", mais toute la COLLECTION a été copiée à cause de liens retour inattendus.

En mettant tout cela ensemble, nous ne pouvons parvenir qu’à une seule conclusion :Nous ne pouvons pas avoir un objectif général, équivalent Delphi à MemberwiseClone.Nous pouvons avoir un sosie partiel pour des objets plus simples avec des interactions simples, mais ce n'est pas aussi attrayant !

Il y a un moyen d'effectuer une copie profonde (clone) d'un objet à Delphi.Cela fonctionne pour les dernières versions de Delphi (2010 et plus).Voir le code coincé ci-dessous ... C'est en fait assez simple et vous n'avez pas besoin de bibliothèques externes.Vous pouvez trouver plus d'informations ici: 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;

Je pense que vous recherchez quelque chose de similaire à celui-ci: http://code.google.com/p/delphilhlplib/source/browse/trunk/library/src/extensions/dehl.cloning.pas

Il ne fonctionnera que sur D2010 et plus (nécessite une RTTI étendue).

J'ai posté un Clonage des composants Répondez à un momentCela pourrait être utile, bien que ce ne soit pas l'équivalent de MemberWiseClone.Cela fonctionne à Delphi aussi loin que D5, je crois, et je suis sûr que cela fonctionne dans D2007.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top