begin process at 2010 02 10 09:35:06
  Trouver un code source :
 
dans
 
Accueil > 

Code

 > 

Astuces

 > METHODE CLONAGE 'DEEPCLONAGE'

METHODE CLONAGE 'DEEPCLONAGE'


 Information sur la source

Note :
9 / 10 - par 1 personne
9,00 / 10

  • 1

  • 2

  • 3

  • 4

  • 5

  • 6

  • 7

  • 8

  • 9

  • 10
Catégorie :Astuces Source .NET ( DotNet ) Classé sous :clone, icloneable, child, deep Niveau :Débutant Date de création :30/11/2005 Date de mise à jour :30/11/2005 14:06:40 Vu / téléchargé :15 399 / 177

Auteur : Renfield

Ecrire un message privé
Ce membre participe au partage de revenus publicitaires
Commentaire sur cette source (10)
Ajouter un commentaire et/ou une note


 Description

MemberwiseClone est pratique, certes, mais elle ne duplique pas les propriétés et fields de type reference : l'objet cloné pointe sur les mêmes objets...
Il est bien sur de définir la méthode Clone pour chacun des 'enfant', et les appeler les uns après les autres.
seulement, si vous ajouter un champs, il faudra penser a modifier en conséquence votre méthode Clone...

je vous propose donc cette classe, a utiliser en tant que classe de base de vos classes à cloner.
Celle-ci implémente la méthode Clone, et parcoure un à un les fields et properties qu'elle contient, et clone le tout.
(Les IEnumerables ne sont pas pris en compte, je pourrais modifier mon code, au besoin)

Source

  • using System;
  • using System.Reflection;
  • public abstract class CDeepCloner : ICloneable
  • {
  • private object Clone(object vObj)
  • {
  • if (vObj.GetType().IsValueType || vObj.GetType() == Type.GetType("System.String"))
  • return vObj;
  • else
  • {
  • object newObject = Activator.CreateInstance(vObj.GetType());
  • foreach (PropertyInfo Item in newObject.GetType().GetProperties())
  • {
  • if (Item.GetType().GetInterface("ICloneable") != null)
  • {
  • ICloneable IClone = (ICloneable)Item.GetValue(vObj, null);
  • Item.SetValue(newObject, IClone.Clone(), null);
  • }
  • else
  • Item.SetValue(newObject, Clone(Item.GetValue(vObj, null)), null);
  • }
  • foreach (FieldInfo Item in newObject.GetType().GetFields())
  • {
  • if (Item.GetType().GetInterface("ICloneable") != null)
  • {
  • ICloneable IClone = (ICloneable)Item.GetValue(vObj);
  • Item.SetValue(newObject, IClone.Clone());
  • }
  • else
  • Item.SetValue(newObject, Clone(Item.GetValue(vObj)));
  • }
  • return newObject;
  • }
  • }
  • public object Clone()
  • {
  • return Clone(this);
  • }
  • }
using System;
using System.Reflection;

public abstract class CDeepCloner : ICloneable
{
    private object Clone(object vObj)
    {
        if (vObj.GetType().IsValueType || vObj.GetType() == Type.GetType("System.String"))
            return vObj;
        else
        {
            object newObject = Activator.CreateInstance(vObj.GetType());

            foreach (PropertyInfo Item in newObject.GetType().GetProperties())
            {
                if (Item.GetType().GetInterface("ICloneable") != null)
                {
                    ICloneable IClone = (ICloneable)Item.GetValue(vObj, null);
                    Item.SetValue(newObject, IClone.Clone(), null);
                }
                else
                    Item.SetValue(newObject, Clone(Item.GetValue(vObj, null)), null);
            }

            foreach (FieldInfo Item in newObject.GetType().GetFields())
            {
                if (Item.GetType().GetInterface("ICloneable") != null)
                {
                    ICloneable IClone = (ICloneable)Item.GetValue(vObj);
                    Item.SetValue(newObject, IClone.Clone());
                }
                else
                    Item.SetValue(newObject, Clone(Item.GetValue(vObj)));
            }
            return newObject;
        }
    }

    public object Clone()
    {
        return Clone(this);
    }
}


 Fichier Zip

Les Membres Club peuvent télécharger directement un fichier contenu dans le zip sans télécharger le zip en entier !

Télécharger le zip


 Historique

30 novembre 2005 14:06:41 :
J'ai ajoute le clonage des fields et propriétés privées

 Sources du même auteur

Source avec Zip Source .NET (Dotnet) CLASSE AIDANT A L'EXECUTION DES PROCÉDURES STOCKÉES (VS2005)

 Sources de la même categorie

Source avec une capture Source .NET (Dotnet) AJOUTER DES BYTES À UN EXECUTABLE par t0fx
Source .NET (Dotnet) COPIER/ COLLER DATAGRID (COPY/PASTE) par jamesbidon
Source avec Zip Source .NET (Dotnet) MECANISME DE SYNCHRONISATION DE THREAD - MONITOR, MUTEX, SEM... par jesusonline
Source .NET (Dotnet) EVENTHANDLERS GÉNÉRIQUES par ricklekebekoi
Source avec Zip Source .NET (Dotnet) TRAITER UN FOREACH EN PARALLÈLE par maitredede

 Sources en rapport avec celle ci

Source avec Zip Source .NET (Dotnet) EXEMPLE DE CLONAGE D'UNE CLASSE DÉRIVÉE DE TREENODE par Crazyht
Source avec Zip Source avec une capture Source .NET (Dotnet) INTERACTION PARENT - CHILD (MDI) par gg00xiv

Commentaires et avis

Commentaire de sebmafate le 30/11/2005 16:14:43 administrateur CS

Nickel... mais n'oublie pas de cocher la case 'Ceci est une source .net' ;)

Commentaire de Renfield le 30/11/2005 16:43:45 administrateur CS

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 ^^)

Commentaire de sebmafate le 30/11/2005 16:51:04 administrateur CS

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...

Commentaire de TheSaib le 01/12/2005 00:12:37 administrateur CS

En terme de perf çà donne quoi ?

Commentaire de Renfield le 01/12/2005 00:16:38 administrateur CS

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...

Commentaire de TheSaib le 01/12/2005 00:21:25 administrateur CS

Tu as benchmarqué ou pas ?
Si à l'occasion tu le fais ca m'interresserait :)

Commentaire de Bubuss le 08/08/2006 11:07:30

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

Commentaire de spikeyz le 28/08/2006 16:46: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;
        }

Commentaire de kimwu le 03/11/2009 11:50:33


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

:)

Commentaire de kimwu le 03/11/2009 11:53:13


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)

 Ajouter un commentaire


Discussions en rapport avec ce code source dans le forum

relation MDI child / parent [ par zouzounet ] bonjour :)tout d'abord, bonnes paques à tous :)j'ai ensuite une tite question qui me tracasse mon code :je suis sur une appli mdi, avec des child... l Communication inter-Fenetre (MDI Child vers Parent) [ par Neptune84 ] Je voudrais faire la chose suivante :WinFormPrinc est la fenetre Parent avec un menu menuItem6. Ce menu ouvre (Création) une fenetre MessageUn. Le pro clone d'un controle [ par Fildomen ] sltj'ai un panel ou ya presque 5 controles, et se panel je doit le cloner 5 fois, et pour chacune, je modifierai le panel,comment faire stp pour clone PQ ListViewItem.Clone() ne clone pas tout ? [ par disolheid ] Bonjour (bonsoir) à tous,Pourriez vous me dire pq : ListViewItem clone = (ListViewItem)lvi.Clone();les propriétés "imageindex", "text", Liens entre MDI Child [ par dals ] Salut à tous ceux qui liront mon msg!!! Je débute en VB .Net et mon soucis est d'arriver à établir un lien entre 2 de mes fen&#234 Overwrite de la méthode Clone() [ par Globinours ] Voilà mon problème est simple je veux cloner des TreeNode mais ensuite le casté dans un type dérivant de TreeNode qui contient seu Clone de collection [ par zebobo5 ] Bijour bijour tt le monde Dites comment fait-on pour cloner une collection, g un peu la flème de me tapper tt un traitement. Merchy ZeBobo5 [C#] MDI child et MDI parent : Laison [ par MickParadiseLost ] Bonjour a tous, J'ai une barre d'outils dans ma forme principale et elle contient un pinceau et une gomme. J'aimerai pouvoir peindre avec mon pinceau [C#] MDI: passage de paramêtres [ par MickParadiseLost ] Bonne nuit a tous, J'aimerais connaitre la méthode la plus simple pour pouvoir dessiner dans ma fenetre MDI child lorsque je clique sur un bouton problème pour réactiver mon menu [ par ratsimisampy ] voici mon problème: jai deux form, parent et child jouvre mon child grace a un menu que je rend inactif lorsque je ferme mon child, je voudrai


Nos sponsors


Sondage...

CalendriCode

Février 2010
LMMJVSD
1234567
891011121314
15161718192021
22232425262728

Consulter la suite du CalendriCode

 
Développement réalisé par Nicolas SOREL (Nix) avec l'aide de : Cyril DURAND et Emmanuel (EBArtSoft), Merci à Vincent pour ses précieux conseils.
CodeS-SourceS.com© Toute reproduction même partielle est interdite sauf accord écrit du Webmaster
CodeS-SourceS.com© est une marque déposée tous droits réservés

Google Coop CodeS-SourceS Google Coop CodeS-SourceS
Temps d'éxécution de la page : 0,562 sec (3)

Nous contacter | Annoncer sur CodeS-SourceS | Mentions légales