Archive

Posts Tagged ‘software-development’

C# Deep object copy using MemberwiseClone

July 6, 2012 9 comments

I wrote a nice extensions method for Object type that allows to create a deep copy (clone) of any Object, it doesn’t require default constructor, or any attributes, it works on any object. Unlike BinaryFormatter based clone method.

 

Performance is 3 times faster then BinaryFormatter, here are results of cloning 1000 complex object graphs (20-30 different Objects types).

BinaryFormatter : 1000 iterations / 1037ms

MemberwiseClone: 1000 iterations / 298ms

 

        private static Object InternalCopy(Object originalObject, IDictionary<Object, Object> visited)
        {
            if (originalObject == null) return null;
            var originalObjectType = originalObject.GetType();
            if (IsPrimitive(originalObjectType)) return originalObject;
            if (visited.ContainsKey(originalObject)) return visited[originalObject];
            var cloneObject = CloneMethod.Invoke(originalObject, null);
            visited.Add(originalObject, cloneObject);

            foreach (FieldInfo fieldInfo in originalObjectType.GetFields(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.FlattenHierarchy))
            {
                if (IsPrimitive(fieldInfo.FieldType)) continue;
                var originalFieldValue = fieldInfo.GetValue(originalObject);
                var clonedFieldValue = originalFieldValue == null ? null : InternalCopy(originalFieldValue, visited);
                fieldInfo.SetValue(cloneObject, clonedFieldValue);
                if (clonedFieldValue == null) continue;
                if (fieldInfo.FieldType.IsArray)
                {
                    var arrayType = fieldInfo.FieldType.GetElementType();
                    if (IsPrimitive(arrayType)) continue;
                    Array clonedArray = (Array)clonedFieldValue;
                    for (long i = 0; i < clonedArray.LongLength; i++) clonedArray.SetValue(InternalCopy(clonedArray.GetValue(i), visited), i);
                }
            }
            return cloneObject;
        }

Latest full source code can be found at: https://raw.github.com/Burtsev-Alexey/net-object-deep-copy/master/ObjectExtensions.cs

Advertisements
%d bloggers like this: