/// <summary> /// Creates a deep copy of an object using the supplied dictionary of visited objects as /// a source of objects already encountered in the copy traversal. The dictionary of visited /// objects is used for holding objects that have already been copied, to avoid erroneous /// duplication of parts of the object graph. /// </summary> /// <param name="instance">The object to be copied.</param> /// <param name="visited">The graph of objects visited so far.</param> /// <returns></returns> private static object Clone(this object instance, VisitedGraph visited) { if (instance == null) { return(null); } Type instanceType = instance.GetType(); if (typeof(Type).IsAssignableFrom(instanceType)) { return(instance); } if (instanceType.IsPointer || instanceType == typeof(Pointer) || instanceType.IsPrimitive || instanceType == typeof(string)) { return(instance); // Pointers, primitive types and strings are considered immutable } if (instanceType.IsArray) { int length = ((Array)instance).Length; Array copied = (Array)Activator.CreateInstance(instanceType, length); visited.Add(instance, copied); for (int i = 0; i < length; ++i) { copied.SetValue(((Array)instance).GetValue(i).Clone(visited), i); } return(copied); } return(Clone(instance, visited, DeduceInstance(instance))); }
/// <summary> /// Creates a deep copy of an object using the supplied dictionary of visited objects as /// a source of objects already encountered in the copy traversal. The dictionary of visited /// objects is used for holding objects that have already been copied, to avoid erroneous /// duplication of parts of the object graph. /// </summary> /// <param name="instance">The object to be copied.</param> /// <param name="visited">The graph of objects visited so far.</param> /// <returns></returns> private static object Clone(this object instance, VisitedGraph visited) { if (instance == null) { return(null); } Type instanceType = instance.GetType(); if (instanceType.IsValueType || instanceType == typeof(string)) { return(instance); // Value types and strings are immutable } else if (instanceType.IsArray) { int length = ((Array)instance).Length; Array copied = (Array)Activator.CreateInstance(instanceType, length); visited.Add(instance, copied); for (int i = 0; i < length; ++i) { copied.SetValue(((Array)instance).GetValue(i).Clone(visited), i); } return(copied); } else { return(Clone(instance, visited, DeduceInstance(instance))); } }
private static object Clone(this object instance, VisitedGraph visited, object copy) { if (visited.ContainsKey(instance)) { return(visited[instance]); } else { visited.Add(instance, copy); } Type type = instance.GetType(); while (type != null) { foreach (FieldInfo field in type.GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance)) { object value = field.GetValue(instance); if (visited.ContainsKey(value)) { field.SetValue(copy, visited[value]); } else { field.SetValue(copy, value.Clone(visited)); } } type = type.BaseType; } return(copy); }
private static object Clone(this object instance, VisitedGraph visited, object copy) { visited.Add(instance, copy); foreach ( FieldInfo field in instance.GetType().GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance)) { object value = field.GetValue(instance); if (visited.ContainsKey(value)) { field.SetValue(copy, visited[value]); } else { field.SetValue(copy, value.Clone(visited)); } } return(copy); }