Exemplo n.º 1
0
        public T Clone <T>(T source)
        {
            // Don't clone a null object or immutable objects. Return the identical reference in these cases
            if (source == null || ImmutableTypeSet.IsImmutableType(source.GetType()))
            {
                return(source);
            }
            // Try to access current "in-use" ObjectCopierState first
            ObjectCopierState ocState = usedOcStateTL.Value;

            if (ocState != null)
            {
                // Reuse TL instance. And do not bother with cleanup
                return(CloneRecursive(source, ocState));
            }
            // No ObjectCopierState "in-use". So we set the TL instance "in-use" and clean it up in the end
            // because we are responsible for this in this case
            ocState             = AcquireObjectCopierState();
            usedOcStateTL.Value = ocState;
            try
            {
                return(CloneRecursive(source, ocState));
            }
            finally
            {
                // Clear "in-use" instance
                usedOcStateTL.Value = null;
                // Cleanup ObjectCopierState to allow reusage in the same thread later
                ocState.Clear();
            }
        }
Exemplo n.º 2
0
        protected Object CloneCollection(Object source, ObjectCopierState ocState)
        {
            Type        objType   = source.GetType();
            IEnumerable cloneColl = (IEnumerable)Activator.CreateInstance(objType);

            ocState.objectToCloneDict.Add(source, cloneColl);

            // The problem is that .NET does not have a holistic interface to add items to a collection
            MethodInfo addMethod = cloneColl.GetType().GetMethod("Add");

            Object[] args = ocState.addArgs;
            try
            {
                foreach (Object item in (IEnumerable)source)
                {
                    // Clone each item of the IEnumerable
                    Object cloneItem = CloneRecursive(item, ocState);
                    args[0] = cloneItem;
                    addMethod.Invoke(cloneColl, args);
                }
                return(cloneColl);
            }
            finally
            {
                args[0] = null;
            }
        }
Exemplo n.º 3
0
        protected Object CloneDefault(Object source, ObjectCopierState ocState)
        {
            Type   objType = source.GetType();
            Object clone   = Activator.CreateInstance(objType);

            ocState.objectToCloneDict.Add(source, clone);
            DeepCloneProperties(source, clone, ocState);
            return(clone);
        }
Exemplo n.º 4
0
        protected ObjectCopierState AcquireObjectCopierState()
        {
            // Creates automatically a valid instance if this thread does not already have one
            ObjectCopierState ocState = ocStateTL.Value;

            if (ocState == null)
            {
                ocState         = new ObjectCopierState(this);
                ocStateTL.Value = ocState;
            }
            return(ocState);
        }
Exemplo n.º 5
0
 internal void DeepCloneProperties(Object source, Object clone, ObjectCopierState ocState)
 {
     IPropertyInfo[] properties = PropertyInfoProvider.GetPrivateProperties(source.GetType());
     foreach (IPropertyInfo property in properties)
     {
         if (!property.IsWritable)
         {
             continue;
         }
         Object objValue   = property.GetValue(source);
         Object cloneValue = CloneRecursive(objValue, ocState);
         property.SetValue(clone, cloneValue);
     }
 }
Exemplo n.º 6
0
        /// <summary>
        /// Gets called by the ObjectCopierState on custom / default behavior switches
        /// </summary>
        internal T CloneRecursive <T>(T source, ObjectCopierState ocState)
        {
            // Don't clone a null object or immutable objects. Return the identical reference in these cases
            if (source == null || ImmutableTypeSet.IsImmutableType(source.GetType()))
            {
                return(source);
            }
            Type objType = source.GetType();
            IdentityDictionary <Object, Object> objectToCloneDict = ocState.objectToCloneDict;
            Object clone = DictionaryExtension.ValueOrDefault(ocState.objectToCloneDict, source);

            if (clone != null)
            {
                // Object has already been cloned. Cycle detected - we are finished here
                return((T)clone);
            }
            if (objType.IsArray)
            {
                return((T)CloneArray(source, ocState));
            }
            if (source is IEnumerable && !(source is String))
            {
                return((T)CloneCollection(source, ocState));
            }
            // Check whether the object will be copied by custom behavior
            IObjectCopierExtension extension = extensions.GetExtension(objType);

            if (extension != null)
            {
                clone = extension.DeepClone(source, ocState);
                objectToCloneDict.Add(source, clone);
                return((T)clone);
            }
            // Copy by default behavior
            return((T)CloneDefault(source, ocState));
        }
Exemplo n.º 7
0
        protected Object CloneArray(Object source, ObjectCopierState ocState)
        {
            Type  objType     = source.GetType();
            Array array       = (Array)(Object)source;
            Type  elementType = objType.GetElementType();
            int   length      = array.Length;
            Array cloneArray  = Array.CreateInstance(elementType, length);

            ocState.objectToCloneDict.Add(source, cloneArray);
            if (ImmutableTypeSet.IsImmutableType(elementType))
            {
                // Clone native array with native functionality for performance reasons
                Array.Copy(array, cloneArray, length);
            }
            else
            {
                for (int a = length; a-- > 0;)
                {
                    // Clone each item of the array
                    cloneArray.SetValue(CloneRecursive(array.GetValue(a), ocState), a);
                }
            }
            return(cloneArray);
        }