Пример #1
0
        internal static T[] CopyArrayRank1 <T>(T[] originalArray, CopyContext context)
        {
            if (context.TryGetCopy(originalArray, out var existingCopy))
            {
                return((T[])existingCopy);
            }

            var length = originalArray.Length;
            var result = new T[length];

            context.RecordCopy(originalArray, result);
            for (var i = 0; i < length; i++)
            {
                var original = originalArray[i];
                if (original != null)
                {
                    if (context.TryGetCopy(original, out var existingElement))
                    {
                        result[i] = (T)existingElement;
                    }
                    else
                    {
                        var copy = CopierGenerator <T> .Copy(original, context);

                        context.RecordCopy(original, copy);
                        result[i] = copy;
                    }
                }
            }
            return(result);
        }
Пример #2
0
        internal static T[,] CopyArrayRank2 <T>(T[,] originalArray, CopyContext context)
        {
            if (context.TryGetCopy(originalArray, out var existingCopy))
            {
                return((T[, ])existingCopy);
            }

            var lenI   = originalArray.GetLength(0);
            var lenJ   = originalArray.GetLength(1);
            var result = new T[lenI, lenJ];

            context.RecordCopy(originalArray, result);
            for (var i = 0; i < lenI; i++)
            {
                for (var j = 0; j < lenJ; j++)
                {
                    var original = originalArray[i, j];
                    if (original != null)
                    {
                        if (context.TryGetCopy(original, out var existingElement))
                        {
                            result[i, j] = (T)existingElement;
                        }
                        else
                        {
                            var copy = CopierGenerator <T> .Copy(original, context);

                            context.RecordCopy(original, copy);
                            result[i, j] = copy;
                        }
                    }
                }
            }
            return(result);
        }
Пример #3
0
        /// <summary>
        /// Creates and returns a deep copy of the provided object.
        /// </summary>
        /// <typeparam name="T">The object type.</typeparam>
        /// <param name="original">The object to copy.</param>
        /// <param name="context">
        /// The copy context, providing referential integrity between multiple calls to this method.
        /// </param>
        /// <returns>A deep copy of the provided object.</returns>
        public static T Copy <T>(T original, CopyContext context)
        {
            if (original == null)
            {
                return(default(T));
            }

            // If this object has already been copied, return that copy.
            var existingCopy = context.TryGetCopy(original);

            if (existingCopy != null)
            {
                return((T)existingCopy);
            }

            var type = original.GetType();

            if (!type.IsValueType)
            {
                // Handle arrays specially.
                var originalArray = original as Array;
                if (originalArray != null)
                {
                    return((T)CopyArray(originalArray, context));
                }
            }

            var typedCopier = CopierGenerator.GetOrCreateCopier <T>(type);

            return(typedCopier(original, context));
        }
Пример #4
0
        internal static T CopyArray <T>(T original, CopyContext context)
        {
            if (context.TryGetCopy(original, out var existingCopy))
            {
                return((T)existingCopy);
            }

            var originalArray = original as Array;

            if (originalArray == null)
            {
                throw new InvalidCastException($"Cannot cast non-array type {original?.GetType()} to Array.");
            }
            var elementType = original.GetType().GetElementType();

            var rank    = originalArray.Rank;
            var lengths = new int[rank];

            for (var i = 0; i < rank; i++)
            {
                lengths[i] = originalArray.GetLength(i);
            }

            var copyArray = Array.CreateInstance(elementType, lengths);

            context.RecordCopy(originalArray, copyArray);

            if (DeepCopier.CopyPolicy.IsShallowCopyable(elementType))
            {
                Array.Copy(originalArray, copyArray, originalArray.Length);
            }

            var index = new int[rank];
            var sizes = new int[rank];

            sizes[rank - 1] = 1;
            for (var k = rank - 2; k >= 0; k--)
            {
                sizes[k] = sizes[k + 1] * lengths[k + 1];
            }

            for (var i = 0; i < originalArray.Length; i++)
            {
                var k = i;
                for (var n = 0; n < rank; n++)
                {
                    var offset = k / sizes[n];
                    k        = k - offset * sizes[n];
                    index[n] = offset;
                }

                copyArray.SetValue(DeepCopier.Copy(originalArray.GetValue(index), context), index);
            }

            return((T)(object)copyArray);
        }
Пример #5
0
        internal static T[] CopyArrayRank1Shallow <T>(T[] array, CopyContext context)
        {
            if (context.TryGetCopy(array, out var existingCopy))
            {
                return((T[])existingCopy);
            }

            var length = array.Length;
            var result = new T[length];

            context.RecordCopy(array, result);
            Array.Copy(array, result, length);
            return(result);
        }
Пример #6
0
        internal static T[,] CopyArrayRank2Shallow <T>(T[,] array, CopyContext context)
        {
            if (context.TryGetCopy(array, out var existingCopy))
            {
                return((T[, ])existingCopy);
            }

            var lenI   = array.GetLength(0);
            var lenJ   = array.GetLength(1);
            var result = new T[lenI, lenJ];

            context.RecordCopy(array, result);
            Array.Copy(array, result, array.Length);
            return(result);
        }
Пример #7
0
        internal static T[] CopyArrayRank1 <T>(T[] originalArray, CopyContext context)
        {
            if (context.TryGetCopy(originalArray, out var existingCopy))
            {
                return((T[])existingCopy);
            }

            var length = originalArray.Length;
            var result = new T[length];

            context.RecordCopy(originalArray, result);
            for (var i = 0; i < length; i++)
            {
                result[i] = CopierGenerator <T> .Copy(originalArray[i], context);
            }
            return(result);
        }