Esempio n. 1
0
        private static List <T> Copy <T>(List <T> source, CopyContext context)
        {
            if (context.TryGetCopy(source, out var existingCopy))
            {
                return((List <T>)existingCopy);
            }

            var length = source.Count;
            var target = new List <T>(length);

            context.RecordCopy(source, target);

            for (var i = 0; i < length; i++)
            {
                T sourceItem = source[i];

                if (sourceItem != null)
                {
                    target.Add(Cloner <T> .Get(sourceItem, context));
                }
                else
                {
                    target.Add(sourceItem);
                }
            }

            return(target);
        }
Esempio n. 2
0
        private static T Copy <T>(T source, CopyContext context)
        {
            if (context.TryGetCopy(source, out var existingCopy))
            {
                return((T)existingCopy);
            }

            if (!(source is Array sourceAsArray))
            {
                throw new InvalidCastException($"Cannot cast non-array type {source?.GetType()} to Array.");
            }

            var elementType = source.GetType().GetElementType();

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

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

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

            context.RecordCopy(sourceAsArray, target);
            Array.Copy(sourceAsArray, target, sourceAsArray.Length);

            return((T)(object)target);
        }
Esempio n. 3
0
        private static T[,] Copy <T>(T[,] source, CopyContext context)
        {
            if (context.TryGetCopy(source, out var existingCopy))
            {
                return((T[, ])existingCopy);
            }

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

            context.RecordCopy(source, target);

            for (var i = 0; i < lenI; i++)
            {
                for (var j = 0; j < lenJ; j++)
                {
                    T sourceItem = source[i, j];

                    if (sourceItem != null)
                    {
                        target[i, j] = Cloner <T> .Get(sourceItem, context);
                    }
                }
            }

            return(target);
        }
Esempio n. 4
0
        public object DeepCopy(object input, CopyContext context)
        {
            if (context.TryGetCopy <object>(input, out var result))
            {
                return(result);
            }

            ThrowNotNullException(input);
            return(null);
        }
Esempio n. 5
0
        /// <summary>
        /// Creates a deep copy of the provided input.
        /// </summary>
        /// <param name="input">The input.</param>
        /// <param name="context">The context.</param>
        /// <returns>A copy of <paramref name="input" />.</returns>
        public static byte[] DeepCopy(byte[] input, CopyContext context)
        {
            if (context.TryGetCopy <byte[]>(input, out var result))
            {
                return(result);
            }

            result = new byte[input.Length];
            context.RecordCopy(input, result);
            input.CopyTo(result.AsSpan());
            return(result);
        }
Esempio n. 6
0
        private static T[,] Copy <T>(T[,] source, CopyContext context)
        {
            if (context.TryGetCopy(source, out var existingCopy))
            {
                return((T[, ])existingCopy);
            }

            var result = new T[source.GetLength(0), source.GetLength(1)];

            context.RecordCopy(source, result);
            Array.Copy(source, result, source.Length);
            return(result);
        }
Esempio n. 7
0
    /// <inheritdoc/>
    public TField DeepCopy(TField input, CopyContext context)
    {
        if (context.TryGetCopy <TField>(input, out var result))
        {
            return(result);
        }

        var surrogate = _converter.ConvertToSurrogate(in input);
        var copy      = _surrogateCopier.DeepCopy(surrogate, context);

        result = _converter.ConvertFromSurrogate(in copy);

        context.RecordCopy(input, result);
        return(result);
    }
Esempio n. 8
0
        public T[] DeepCopy(T[] input, CopyContext context)
        {
            if (context.TryGetCopy <T[]>(input, out var result))
            {
                return(result);
            }

            result = new T[input.Length];
            context.RecordCopy(input, result);
            for (var i = 0; i < input.Length; i++)
            {
                result[i] = _elementCopier.DeepCopy(input[i], context);
            }

            return(result);
        }
Esempio n. 9
0
        public Tuple <T> DeepCopy(Tuple <T> input, CopyContext context)
        {
            if (context.TryGetCopy(input, out Tuple <T> result))
            {
                return(result);
            }

            if (input.GetType() != typeof(Tuple <T>))
            {
                return(context.Copy(input));
            }

            result = new Tuple <T>(_copier.DeepCopy(input.Item1, context));
            context.RecordCopy(input, result);
            return(result);
        }
Esempio n. 10
0
            public Dictionary <X, Y> GetClone(Dictionary <X, Y> source, CopyContext context)
            {
                if (context.TryGetCopy(source, out var existingCopy))
                {
                    return((Dictionary <X, Y>)existingCopy);
                }

                var target = new Dictionary <X, Y>(source.Count, source.Comparer);

                context.RecordCopy(source, target);

                foreach (var pair in source)
                {
                    target.Add(KeyCloner(pair.Key, context), ValueCloner(pair.Value, context));
                }

                return(target);
            }
Esempio n. 11
0
        public object DeepCopy(object input, CopyContext context)
        {
            if (context.TryGetCopy <object>(input, out var result))
            {
                return(result);
            }

            var type = input.GetType();

            if (type != typeof(object))
            {
                return(context.Copy(input));
            }

            result = new object();
            context.RecordCopy(input, result);
            return(result);
        }
Esempio n. 12
0
        /// <inheritdoc />
        public SortedDictionary <TKey, TValue> DeepCopy(SortedDictionary <TKey, TValue> input, CopyContext context)
        {
            if (context.TryGetCopy <SortedDictionary <TKey, TValue> >(input, out var result))
            {
                return(result);
            }

            if (input.GetType() != typeof(SortedDictionary <TKey, TValue>))
            {
                return(context.Copy(input));
            }

            result = new SortedDictionary <TKey, TValue>(input.Comparer);
            context.RecordCopy(input, result);
            foreach (var pair in input)
            {
                result[_keyCopier.DeepCopy(pair.Key, context)] = _valueCopier.DeepCopy(pair.Value, context);
            }

            return(result);
        }
Esempio n. 13
0
        /// <inheritdoc/>
        public List <T> DeepCopy(List <T> input, CopyContext context)
        {
            if (context.TryGetCopy <List <T> >(input, out var result))
            {
                return(result);
            }

            if (input.GetType() != typeof(List <T>))
            {
                return(context.DeepCopy(input));
            }

            result = new List <T>(input.Count);
            context.RecordCopy(input, result);
            foreach (var item in input)
            {
                result.Add(_copier.DeepCopy(item, context));
            }

            return(result);
        }
Esempio n. 14
0
        /// <inheritdoc />
        public SortedSet <T> DeepCopy(SortedSet <T> input, CopyContext context)
        {
            if (context.TryGetCopy <SortedSet <T> >(input, out var result))
            {
                return(result);
            }

            if (input.GetType() != typeof(SortedSet <T>))
            {
                return(context.Copy(input));
            }

            result = new SortedSet <T>(input.Comparer);
            context.RecordCopy(input, result);
            foreach (var element in input)
            {
                result.Add(_elementCopier.DeepCopy(element, context));
            }

            return(result);
        }
        /// <inheritdoc/>
        public NameValueCollection DeepCopy(NameValueCollection input, CopyContext context)
        {
            if (context.TryGetCopy <NameValueCollection>(input, out var result))
            {
                return(result);
            }

            if (input.GetType() != typeof(NameValueCollection))
            {
                return(context.DeepCopy(input));
            }

            result = new NameValueCollection(input.Count);
            context.RecordCopy(input, result);
            for (var i = 0; i < input.Count; i++)
            {
                result.Add(input.GetKey(i), input.Get(i));
            }

            return(result);
        }
        public ConcurrentDictionary <TKey, TValue> DeepCopy(ConcurrentDictionary <TKey, TValue> input, CopyContext context)
        {
            if (context.TryGetCopy <ConcurrentDictionary <TKey, TValue> >(input, out var result))
            {
                return(result);
            }

            if (input.GetType() != typeof(ConcurrentDictionary <TKey, TValue>))
            {
                return(context.Copy(input));
            }

            // Note that this cannot propagate the input's key comparer, since it is not exposed from ConcurrentDictionary.
            result = new ConcurrentDictionary <TKey, TValue>();
            context.RecordCopy(input, result);
            foreach (var pair in input)
            {
                result[_keyCopier.DeepCopy(pair.Key, context)] = _valueCopier.DeepCopy(pair.Value, context);
            }

            return(result);
        }
Esempio n. 17
0
        /// <inheritdoc/>
        public ConcurrentQueue <T> DeepCopy(ConcurrentQueue <T> input, CopyContext context)
        {
            if (context.TryGetCopy <ConcurrentQueue <T> >(input, out var result))
            {
                return(result);
            }

            if (input.GetType() != typeof(ConcurrentQueue <T>))
            {
                return(context.Copy(input));
            }

            // Note that this cannot propagate the input's key comparer, since it is not exposed from ConcurrentDictionary.
            result = new ConcurrentQueue <T>();
            context.RecordCopy(input, result);
            foreach (var item in input)
            {
                result.Enqueue(_copier.DeepCopy(item, context));
            }

            return(result);
        }
Esempio n. 18
0
        public ReadOnlyDictionary <TKey, TValue> DeepCopy(ReadOnlyDictionary <TKey, TValue> input, CopyContext context)
        {
            if (context.TryGetCopy <ReadOnlyDictionary <TKey, TValue> >(input, out var result))
            {
                return(result);
            }

            if (input.GetType() != typeof(ReadOnlyDictionary <TKey, TValue>))
            {
                return(context.Copy(input));
            }

            var temp = new Dictionary <TKey, TValue>(input.Count);

            foreach (var pair in input)
            {
                temp[_keyCopier.DeepCopy(pair.Key, context)] = _valueCopier.DeepCopy(pair.Value, context);
            }

            result = new ReadOnlyDictionary <TKey, TValue>(temp);
            context.RecordCopy(input, result);
            return(result);
        }
Esempio n. 19
0
        private static T[] Copy <T>(T[] source, CopyContext context)
        {
            if (context.TryGetCopy(source, out var existingCopy))
            {
                return((T[])existingCopy);
            }

            var length = source.Length;
            var target = new T[length];

            context.RecordCopy(source, target);

            for (var i = 0; i < length; i++)
            {
                T sourceItem = source[i];

                if (sourceItem != null)
                {
                    target[i] = Cloner <T> .Get(sourceItem, context);
                }
            }

            return(target);
        }
Esempio n. 20
0
        /// <inheritdoc/>
        object IDeepCopier <object> .DeepCopy(object original, CopyContext context)
        {
            if (context.TryGetCopy <Array>(original, out var result))
            {
                return(result);
            }

            var type          = original.GetType();
            var originalArray = (Array)original;
            var elementType   = type.GetElementType();

            if (ShallowCopyableTypes.Contains(elementType))
            {
                return(originalArray.Clone());
            }

            // We assume that all arrays have lower bound 0. In .NET 4.0, it's hard to create an array with a non-zero lower bound.
            var rank    = originalArray.Rank;
            var lengths = new int[rank];

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

            result = Array.CreateInstance(elementType, lengths);
            context.RecordCopy(original, result);

            if (rank == 1)
            {
                for (var i = 0; i < lengths[0]; i++)
                {
                    result.SetValue(_elementCopier.DeepCopy(originalArray.GetValue(i), context), i);
                }
            }
            else if (rank == 2)
            {
                for (var i = 0; i < lengths[0]; i++)
                {
                    for (var j = 0; j < lengths[1]; j++)
                    {
                        result.SetValue(_elementCopier.DeepCopy(originalArray.GetValue(i, j), context), i, j);
                    }
                }
            }
            else
            {
                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++)
                {
                    int k = i;
                    for (int n = 0; n < rank; n++)
                    {
                        int offset = k / sizes[n];
                        k       -= offset * sizes[n];
                        index[n] = offset;
                    }

                    result.SetValue(_elementCopier.DeepCopy(originalArray.GetValue(index), context), index);
                }
            }

            return(result);
        }
Esempio n. 21
0
        private static T Copy <T>(T source, CopyContext context)
        {
            if (context.TryGetCopy(source, out var existingCopy))
            {
                return((T)existingCopy);
            }

            if (!(source is Array sourceAsArray))
            {
                throw new InvalidCastException($"Cannot cast non-array type {source?.GetType()} to Array.");
            }

            var elementType = source.GetType().GetElementType();

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

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

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

            context.RecordCopy(sourceAsArray, target);

            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 < sourceAsArray.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;
                }

                // using objects will cause a performance issue
                // for value types due to boxing/unboxing.
                // TODO: Find a way to deal with this in a strongly
                // typed fashion.
                object sourceItem = sourceAsArray.GetValue(index);

                if (sourceItem != null)
                {
                    target.SetValue(Cloner <object> .Get(sourceItem, context), index);
                }
            }

            return((T)(object)target);
        }