示例#1
0
        /// <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, InstanceCreator.GetInstance(instanceType)));
            }
        }
示例#2
0
        private static object Clone(this object instance, VisitedGraph visited, object copy)
        {
            visited.Add(instance, copy);

            var type = instance.GetType();

            foreach (var field in GetTypeCopyableFieldList(type))
            {
                object value = field.Getter(instance);
                object cloned;
                if (value == null)
                {
                    cloned = null;
                }
                else if (!visited.TryGetValue(value, out cloned))
                {
                    cloned = value.Clone(visited);
                }
                field.Setter(copy, cloned);
            }
            return(copy);
        }