/// <summary> /// Réalise une copie profonde de l'objet /// </summary> /// <param name="originalObject">Objet original à copier</param> /// <param name="visited">Liste des propriétés et valeurs déjà copiées</param> /// <returns>Object copier</returns> private static Object InternalCopy(Object originalObject, IDictionary <Object, Object> visited) { //Si on recoit null on ne fait pas de copie if (originalObject == null) { return(null); } //Récupératino du type de l'objet var typeToReflect = originalObject.GetType(); //Si c'est un type primitif on peut directement le renvoyer car il est passé en copie et non en référence if (PrimitiveTypesHelper.IsPrimitive(typeToReflect)) { return(originalObject); } //Si on a déjà fait la copie on ne va pas la refaire alors on renvoi la copie effectuée if (visited.ContainsKey(originalObject)) { return(visited[originalObject]); } //SI c'est un délégué et qu'on ne peut pas lui assigner notre type on renvoi null if (typeof(Delegate).IsAssignableFrom(typeToReflect)) { return(null); } //Appel de la méthode du framework pour copier les propriétés simples de l'objet var cloneObject = CloneMethod.Invoke(originalObject, null); //Si mon objet est un tableau if (typeToReflect.IsArray) { //Récupération du type des élements contenus dedans var arrayType = typeToReflect.GetElementType(); if (!PrimitiveTypesHelper.IsPrimitive(arrayType)) { Array clonedArray = (Array)cloneObject; for (int i = 0; i < clonedArray.Length; i++) { clonedArray.SetValue(InternalCopy(clonedArray.GetValue(i), visited), i); } //Array clonedArray = (Array)cloneObject; //clonedArray.ForEach((array, indices) => array.SetValue(InternalCopy(clonedArray.GetValue(indices), visited), indices)); } } //Ajout de l'objet actuel dans la liste des visités visited.Add(originalObject, cloneObject); //Copie de tous les champs du type CopyFields(originalObject, visited, cloneObject, typeToReflect); RecursiveCopyBaseTypePrivateFields(originalObject, visited, cloneObject, typeToReflect); return(cloneObject); }
/// <summary> /// Réalise la copie des champs pour l'objet /// </summary> /// <param name="originalObject">Objet dont on copie les champs</param> /// <param name="visited">Liste des objets visités</param> /// <param name="cloneObject">Objet cloné</param> /// <param name="typeToReflect">Type sur lequel on se trouve</param> /// <param name="bindingFlags">Informations sur le type du champs</param> /// <param name="filter">Filtre à effectuer sur les propriétés</param> private static void CopyFields(object originalObject, IDictionary <object, object> visited, object cloneObject, Type typeToReflect, BindingFlags bindingFlags = BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.FlattenHierarchy, Func <FieldInfo, bool> filter = null) { //parcours des propriétés du type foreach (FieldInfo fieldInfo in typeToReflect.GetFields(bindingFlags)) { if ((filter == null || !filter(fieldInfo)) && PrimitiveTypesHelper.IsPrimitive(fieldInfo.FieldType)) { var originalFieldValue = fieldInfo.GetValue(originalObject); var clonedFieldValue = InternalCopy(originalFieldValue, visited); fieldInfo.SetValue(cloneObject, clonedFieldValue); } } }