/// <summary> /// Gets the deep copy /// </summary> /// <param name="source">The object to be copied</param> /// <param name="target">The object which will be the copy</param> /// <param name="copiedObjects">Collection of objects and their copied equivalents. Will be populated and queried during copy.</param> /// <param name="path">Relative path to location where files will be copied to</param> /// <param name="copyValue">Indicates whether the new object should refer to a copy or to the same object</param> private static void Copy(object source, object target, Hashtable copiedObjects, string path, bool copyValue) { if (source is IList) { IList copiedArray = (IList)target; copiedArray.Clear(); for (int j = 0; j < ((IList)source).Count; j++) { object copiedArrayValue = ((IList)source)[j]; if (copyValue) { copiedArrayValue = ObjectSupport.GetCopy(copiedArrayValue, copiedObjects, path); } copiedArray.Add(copiedArrayValue); } } else if (source is IDictionary) { IDictionary copiedArray = (IDictionary)target; copiedArray.Clear(); IDictionaryEnumerator dictionaryEnumerator = ((IDictionary)source).GetEnumerator(); while (dictionaryEnumerator.MoveNext()) { object copiedArrayKey = dictionaryEnumerator.Key; object copiedArrayValue = dictionaryEnumerator.Value; if (copyValue) { copiedArrayKey = ObjectSupport.GetCopy(copiedArrayKey, copiedObjects, path); copiedArrayValue = ObjectSupport.GetCopy(copiedArrayValue, copiedObjects, path); } if (!copiedArray.Contains(copiedArrayKey)) { copiedArray.Add(copiedArrayKey, copiedArrayValue); } } } // Special handling for files else if (source is FileSystemInfo) { if (copyValue && (path != null) && (!path.Trim().Equals(""))) { object copiedValue = CopyFile((FileSystemInfo)source, path); } } else { PropertyInfo[] property = source.GetType().GetProperties(); for (int i = 0; i < property.Length; i++) { object sourceValue = property[i].GetValue(source, null); if (sourceValue != null) { // Default copied value. This is just a reference to the original value object copiedValue = sourceValue; // If the value has been copied before, use the same copied equivalent if (copiedObjects.ContainsKey(sourceValue)) { copiedValue = copiedObjects[sourceValue]; } else { // Determine whether the property is to be copied bool copyPropertyValue = (Boolean)MetaInfo.GetAttributeDefault(source.GetType(), property[i].Name, "ObjectCopy", false); if (copyPropertyValue) { if (property[i].CanWrite) { copiedValue = ObjectSupport.GetCopy(sourceValue, copiedObjects, path); } else { object targetValue = property[i].GetValue(target, null); Copy(sourceValue, targetValue, copiedObjects, path); } } else if ((sourceValue is IList) || (sourceValue is IDictionary)) { object targetValue = property[i].GetValue(target, null); Copy(sourceValue, targetValue, copiedObjects, path, copyPropertyValue); } } // Populate the target object if (property[i].CanWrite) { property[i].SetValue(target, copiedValue, null); } if (!copiedObjects.Contains(sourceValue)) { copiedObjects.Add(sourceValue, copiedValue); } } } } }