METHODE CLONAGE 'DEEPCLONAGE'

sebmafate Messages postés 4936 Date d'inscription lundi 17 février 2003 Statut Membre Dernière intervention 14 février 2014 - 30 nov. 2005 à 16:14
kimwu Messages postés 40 Date d'inscription dimanche 23 novembre 2003 Statut Membre Dernière intervention 25 juin 2011 - 18 mars 2011 à 21:04
Cette discussion concerne un article du site. Pour la consulter dans son contexte d'origine, cliquez sur le lien ci-dessous.

https://codes-sources.commentcamarche.net/source/34850-methode-clonage-deepclonage

kimwu Messages postés 40 Date d'inscription dimanche 23 novembre 2003 Statut Membre Dernière intervention 25 juin 2011 1
18 mars 2011 à 21:04
Avec plaisir..
J'espere qu'elle pourra t'être utilse, perso je m'en sert toujours
Renfield Messages postés 17287 Date d'inscription mercredi 2 janvier 2002 Statut Modérateur Dernière intervention 27 septembre 2021 74
17 mars 2011 à 10:11
J'aime bien cette astuce du Serialize. A retenir, mercu kimwu
kimwu Messages postés 40 Date d'inscription dimanche 23 novembre 2003 Statut Membre Dernière intervention 25 juin 2011 1
3 nov. 2009 à 11:53
J'oubliais : En fait ce que cela fait est de serializer puis de suite DEserializer .. du coup cela crée un clone parfais (Deep clone et non Shalow clone qui eux garde les même references d'objets)
kimwu Messages postés 40 Date d'inscription dimanche 23 novembre 2003 Statut Membre Dernière intervention 25 juin 2011 1
3 nov. 2009 à 11:50
Bonjour,

Je sais que cette source date un peu.. mais je voulais apporter une petite contribution - DeepClone :


public static object DeepClone(object obj)
{
object objResult = null;
using (MemoryStream ms =
new MemoryStream())
{
BinaryFormatter bf =
new BinaryFormatter();
bf.Serialize(ms, obj);

ms.Position = 0;
objResult = bf.Deserialize(ms);
}
return objResult;
}


J'ai essayé cette source et elle fonctionne très bien pour le moment. Je ne suis pas allé plus en détail, car tout ce que j''avais à faire était de deepcloner une generic list(of string).. mais d'apres les commentaires des auteurs cela pourrait deepcloner des objets assez complexes.
credit : http://www.code-magazine.com/Article.aspx?quickid=0601121

:)
spikeyz Messages postés 10 Date d'inscription vendredi 17 octobre 2003 Statut Membre Dernière intervention 21 novembre 2008
28 août 2006 à 16:46
Voila moi je viens de finir une methode un peu plus complete que celle-ci si ca interresse quelqu'un.

public object Clone()
{
//Creation de la nouvelle instance de l'objet
Object newObject = Activator.CreateInstance(this.GetType());

//Recuperation de toutes les proprietes de l'objet
PropertyInfo[] infos = newObject.GetType().GetProperties();

foreach (PropertyInfo info in infos)
{
//Test de la propriete pour savoir si elle supporte l'interface ICloneable
Type ICloneType = info.PropertyType.GetInterface("ICloneable", true);

if (ICloneType != null)
{
//Recuperation de l'interface ICloneable de l'objet
ICloneable IClone = (ICloneable)info.GetValue(this, null);

//utilisation de la methode clone() pour assigner la nouvelle valeur de la propriete
info.SetValue(newObject, IClone.Clone(), null);
}
else
//Si la propriete ne supporte pas l'interface, assignation juste de la valeur
info.SetValue(newObject, info.GetValue(this, null), null);

//Test de la propriete pour savoir si elle supporte l'interface IEnumerable
Type IEnumerabletype = info.PropertyType.GetInterface("IEnumerable", true);

if (IEnumerabletype != null)
{
//Recuperation de l'interface IEnumerable de la propriete
IEnumerable IEnum = (IEnumerable)info.GetValue(this, null);

Type IListType = info.PropertyType.GetInterface("IList", true);
Type IDicType = info.PropertyType.GetInterface("IDictionary", true);

int j = 0;

if (IListType != null)
{
//recuperation de l'interface IList
IList list = (IList)info.GetValue(newObject,null);

foreach (Object obj in IEnum)
{
//Test de l'objet pour savoir si il supporte l'interface ICloneable
ICloneType = obj.GetType().GetInterface("ICloneable", true);

if (ICloneType != null)
{
ICloneable clone = (ICloneable)obj;
list[j] = clone.Clone();
}
j++;
}
}
else if (IDicType != null)
{
//Recuperation de l'interface IDictionary
IDictionary dic = (IDictionary)info.GetValue(newObject,null);

j = 0;

foreach (DictionaryEntry de in IEnum)
{
//Test de l'objet pour savoir si il supporte l'interface ICloneable
ICloneType = de.Value.GetType().GetInterface("ICloneable", true);

if (ICloneType != null)
{
ICloneable clone = (ICloneable)de.Value;
dic[de.Key] = clone.Clone();
}
j++;
}
}
}
}

//Recuperation de tous les champs de cette instance
FieldInfo[] fields = newObject.GetType().GetFields();

foreach (FieldInfo fi in this.GetType().GetFields())
{
//Test du champs pour savoir si il supporte l'interface ICloneable
Type ICloneType = fi.FieldType.GetInterface("ICloneable", true);

if (ICloneType != null)
{
//Recuperation de l'interface ICloneable de l'objet
ICloneable IClone = (ICloneable)fi.GetValue(this);

//utilisation de la methode clone() pour assigner la nouvelle valeur du champs
fi.SetValue(newObject, IClone.Clone());
}
else
{
//Si le champs ne supporte pas l'interface, assignation juste du champs
fi.SetValue(newObject, fi.GetValue(this));
}

//Test du champs pour savoir si il support l'interface IEnumerable
Type IEnumerabletype = fi.FieldType.GetInterface("IEnumerable", true);

if (IEnumerabletype != null)
{
//Recuperation de l'interface IEnumerable du champs
IEnumerable IEnum = (IEnumerable)fi.GetValue(this);

Type IListType = fi.FieldType.GetInterface("IList", true);
Type IDicType = fi.FieldType.GetInterface("IDictionary", true);

int j = 0;

if (IListType != null)
{
//recuperation de l'interface IList
IList list = (IList)fi.GetValue(newObject);

foreach (Object obj in IEnum)
{
//Test de l'objet pour savoir si il supporte l'interface ICloneable
ICloneType = obj.GetType().GetInterface("ICloneable", true);

if (ICloneType != null)
{
ICloneable clone = (ICloneable)obj;
list[j] = clone.Clone();
}
j++;
}
}
else if(IDicType != null)
{
//Recuperation de l'interface IDictionary
IDictionary dic = (IDictionary)fi.GetValue(newObject);

j = 0;

foreach (DictionaryEntry de in IEnum)
{
//Test de l'objet pour savoir si il supporte l'interface ICloneable
ICloneType = de.Value.GetType().GetInterface("ICloneable", true);

if (ICloneType != null)
{
ICloneable clone = (ICloneable)de.Value;
dic[de.Key] = clone.Clone();
}
j++;
}
}
}
}
return newObject;
}
Bubuss Messages postés 147 Date d'inscription samedi 7 juin 2003 Statut Membre Dernière intervention 8 décembre 2007
8 août 2006 à 11:07
Chapeau pour ce code, je l'ai intégré au mien mais comme mes classes héritaient déjà dune autre classe j'ai juste récupérer ta fonction et je l'appelle ponctuellement! ça marche très bien!

Je signale cependant un bug car pour certaine propriété de mes objets je n'avais aucune instanciation de faite donc j'ai rajouté après le premier foreach item:

if (Item.GetValue(vObj, null) != null)
{
(... code ...)
}

Voilà je te remercie pour le partage de ce code Salut!

PS : Je crois que cette vérification est nécessaire seulement dans le premier foreach car je ne penses pas que les champs peuvent être = null
TheSaib Messages postés 2367 Date d'inscription mardi 17 avril 2001 Statut Membre Dernière intervention 26 décembre 2007 23
1 déc. 2005 à 00:21
Tu as benchmarqué ou pas ?
Si à l'occasion tu le fais ca m'interresserait :)
Renfield Messages postés 17287 Date d'inscription mercredi 2 janvier 2002 Statut Modérateur Dernière intervention 27 septembre 2021 74
1 déc. 2005 à 00:16
moins rapide, je suppose, que de tout cloner soit-même, invoquant en cascade, la methode Clone des Classes filles qui le supporte
reste que là, les fistons sont bien clonés, et que l'on a pas a y retoucher sans cesse...
TheSaib Messages postés 2367 Date d'inscription mardi 17 avril 2001 Statut Membre Dernière intervention 26 décembre 2007 23
1 déc. 2005 à 00:12
En terme de perf çà donne quoi ?
sebmafate Messages postés 4936 Date d'inscription lundi 17 février 2003 Statut Membre Dernière intervention 14 février 2014 37
30 nov. 2005 à 16:51
oui et non... comme on me l'a fait remarqué y a pas si longtemps... C# peut aussi vouloir Mono... ou tout autre chose... du moment qu'il existe un compilateur...
Renfield Messages postés 17287 Date d'inscription mercredi 2 janvier 2002 Statut Modérateur Dernière intervention 27 septembre 2021 74
30 nov. 2005 à 16:43
Je suis en train de gonfler la classe, avec la gestion des tableaux, etc...

désolé pour la case .Net .... j'avais pas fais gaffe à sa présence, je veux dire, C# implique .Net (enfin, me semble-t'il ^^)
sebmafate Messages postés 4936 Date d'inscription lundi 17 février 2003 Statut Membre Dernière intervention 14 février 2014 37
30 nov. 2005 à 16:14
Nickel... mais n'oublie pas de cocher la case 'Ceci est une source .net' ;)
Rejoignez-nous