Exemple #1
0
        internal static object CloneClassInternal(object obj, DeepCloneState state)
        {
            if (obj == null)
            {
                return(null);
            }

            var cloner = (Func <object, DeepCloneState, object>)DeepClonerCache.GetOrAddClass(obj.GetType(), t => GenerateCloner(t, true));

            // safe ojbect
            if (cloner == null)
            {
                return(obj);
            }

            // loop
            var knownRef = state.GetKnownRef(obj);

            if (knownRef != null)
            {
                return(knownRef);
            }

            return(cloner(obj, state));
        }
Exemple #2
0
        // when we can't use code generation, we can use these methods
        internal static T[] Clone1DimArraySafeInternal <T>(T[] obj, DeepCloneState state)
        {
            var l        = obj.Length;
            var outArray = new T[l];

            state.AddKnownRef(obj, outArray);
            Array.Copy(obj, outArray, obj.Length);
            return(outArray);
        }
Exemple #3
0
        private static T CloneStructInternal <T>(T obj, DeepCloneState state) // where T : struct
        {
            // no loops, no nulls, no inheritance
            var cloner = GetClonerForValueType <T>();

            // safe ojbect
            if (cloner == null)
            {
                return(obj);
            }

            return(cloner(obj, state));
        }
Exemple #4
0
        internal static T[] Clone1DimArrayClassInternal <T>(T[] obj, DeepCloneState state)
        {
            // not null from called method, but will check it anyway
            if (obj == null)
            {
                return(null);
            }
            var l        = obj.Length;
            var outArray = new T[l];

            state.AddKnownRef(obj, outArray);
            for (var i = 0; i < l; i++)
            {
                outArray[i] = (T)CloneClassInternal(obj[i], state);
            }

            return(outArray);
        }
Exemple #5
0
        // relatively frequent case. specially handled
        internal static T[,] Clone2DimArrayInternal <T>(T[,] obj, DeepCloneState state)
        {
            // not null from called method, but will check it anyway
            if (obj == null)
            {
                return(null);
            }
            var l1       = obj.GetLength(0);
            var l2       = obj.GetLength(1);
            var outArray = new T[l1, l2];

            state.AddKnownRef(obj, outArray);
            if (DeepClonerSafeTypes.CanReturnSameObject(typeof(T)))
            {
                Array.Copy(obj, outArray, obj.Length);
                return(outArray);
            }

            if (typeof(T).GetTypeInfo().IsValueType)
            {
                var cloner = GetClonerForValueType <T>();
                for (var i = 0; i < l1; i++)
                {
                    for (var k = 0; k < l2; k++)
                    {
                        outArray[i, k] = cloner(obj[i, k], state);
                    }
                }
            }
            else
            {
                for (var i = 0; i < l1; i++)
                {
                    for (var k = 0; k < l2; k++)
                    {
                        outArray[i, k] = (T)CloneClassInternal(obj[i, k], state);
                    }
                }
            }

            return(outArray);
        }
Exemple #6
0
        internal static T[] Clone1DimArrayStructInternal <T>(T[] obj, DeepCloneState state)
        {
            // not null from called method, but will check it anyway
            if (obj == null)
            {
                return(null);
            }
            var l        = obj.Length;
            var outArray = new T[l];

            state.AddKnownRef(obj, outArray);
            var cloner = GetClonerForValueType <T>();

            for (var i = 0; i < l; i++)
            {
                outArray[i] = cloner(obj[i], state);
            }

            return(outArray);
        }
Exemple #7
0
        // rare cases, very slow cloning. currently it's ok
        internal static Array CloneAbstractArrayInternal(Array obj, DeepCloneState state)
        {
            // not null from called method, but will check it anyway
            if (obj == null)
            {
                return(null);
            }
            var rank = obj.Rank;

            var lowerBounds = Enumerable.Range(0, rank).Select(obj.GetLowerBound).ToArray();
            var lengths     = Enumerable.Range(0, rank).Select(obj.GetLength).ToArray();
            var idxes       = Enumerable.Range(0, rank).Select(obj.GetLowerBound).ToArray();

            var outArray = Array.CreateInstance(obj.GetType().GetElementType(), lengths, lowerBounds);

            state.AddKnownRef(obj, outArray);
            while (true)
            {
                outArray.SetValue(CloneClassInternal(obj.GetValue(idxes), state), idxes);
                var ofs = rank - 1;
                while (true)
                {
                    idxes[ofs]++;
                    if (idxes[ofs] >= lowerBounds[ofs] + lengths[ofs])
                    {
                        idxes[ofs] = lowerBounds[ofs];
                        ofs--;
                        if (ofs < 0)
                        {
                            return(outArray);
                        }
                    }
                    else
                    {
                        break;
                    }
                }
            }
        }