Пример #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));
        }
Пример #2
0
 internal static T[] Clone1DimArraySafeInternal <T>(T[] obj, DeepCloneState state)
 {
     T[] array = new T[obj.Length];
     state.AddKnownRef(obj, array);
     Array.Copy(obj, array, obj.Length);
     return(array);
 }
Пример #3
0
 internal static Array CloneAbstractArrayInternal(Array obj, DeepCloneState state)
 {
     if (obj != null)
     {
         int   rank   = obj.Rank;
         int[] array  = Enumerable.Range(0, rank).Select(obj.GetLowerBound).ToArray();
         int[] array2 = Enumerable.Range(0, rank).Select(obj.GetLength).ToArray();
         int[] array3 = Enumerable.Range(0, rank).Select(obj.GetLowerBound).ToArray();
         Array array4 = Array.CreateInstance(obj.GetType().GetElementType(), array2, array);
         state.AddKnownRef(obj, array4);
         while (true)
         {
             array4.SetValue(CloneClassInternal(obj.GetValue(array3), state), array3);
             int num = rank - 1;
             while (true)
             {
                 array3[num]++;
                 if (array3[num] < array[num] + array2[num])
                 {
                     break;
                 }
                 array3[num] = array[num];
                 num--;
                 if (num < 0)
                 {
                     return(array4);
                 }
             }
         }
     }
     return(null);
 }
Пример #4
0
        internal static T[] Clone1DimArraySafeInternal <T>(T[] objFrom, T[] objTo, DeepCloneState state)
        {
            int length = Math.Min(objFrom.Length, objTo.Length);

            state.AddKnownRef(objFrom, objTo);
            Array.Copy(objFrom, objTo, length);
            return(objTo);
        }
Пример #5
0
        internal static T[,] Clone2DimArrayInternal <T>(T[,] objFrom, T[,] objTo, DeepCloneState state, bool isDeep)
        {
            if (objFrom == null || objTo == null)
            {
                return(null);
            }
            int num  = Math.Min(objFrom.GetLength(0), objTo.GetLength(0));
            int num2 = Math.Min(objFrom.GetLength(1), objTo.GetLength(1));

            state.AddKnownRef(objFrom, objTo);
            if ((!isDeep || DeepClonerSafeTypes.CanNotCopyType(typeof(T), null)) && objFrom.GetLength(0) == objTo.GetLength(0) && objFrom.GetLength(1) == objTo.GetLength(1))
            {
                Array.Copy(objFrom, objTo, objFrom.Length);
                return(objTo);
            }
            if (!isDeep)
            {
                for (int i = 0; i < num; i++)
                {
                    for (int j = 0; j < num2; j++)
                    {
                        int num3 = i;
                        int num4 = j;
                        T   val  = objFrom[i, j];
                        objTo[num3, num4] = val;
                    }
                }
                return(objTo);
            }
            if (typeof(T).IsValueType())
            {
                Func <T, DeepCloneState, T> clonerForValueType = DeepClonerGenerator.GetClonerForValueType <T>();
                for (int k = 0; k < num; k++)
                {
                    for (int l = 0; l < num2; l++)
                    {
                        int num5 = k;
                        int num6 = l;
                        T   val2 = clonerForValueType(objFrom[k, l], state);
                        objTo[num5, num6] = val2;
                    }
                }
            }
            else
            {
                for (int m = 0; m < num; m++)
                {
                    for (int n = 0; n < num2; n++)
                    {
                        int num7 = m;
                        int num8 = n;
                        T   obj  = (T)DeepClonerGenerator.CloneClassInternal(objFrom[m, n], state);
                        objTo[num7, num8] = obj;
                    }
                }
            }
            return(objTo);
        }
Пример #6
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);
        }
Пример #7
0
        private static T CloneStructInternal <T>(T obj, DeepCloneState state)
        {
            Func <T, DeepCloneState, T> clonerForValueType = GetClonerForValueType <T>();

            if (clonerForValueType == null)
            {
                return(obj);
            }
            return(clonerForValueType(obj, state));
        }
Пример #8
0
        internal static T[,] Clone2DimArrayInternal <T>(T[,] objFrom, T[,] objTo, DeepCloneState state, bool isDeep)
        {
            // not null from called method, but will check it anyway
            if (objFrom == null || objTo == null)
            {
                return(null);
            }
            var l1 = Math.Min(objFrom.GetLength(0), objTo.GetLength(0));
            var l2 = Math.Min(objFrom.GetLength(1), objTo.GetLength(1));

            state.AddKnownRef(objFrom, objTo);
            if ((!isDeep || DeepClonerSafeTypes.CanReturnSameObject(typeof(T))) &&
                objFrom.GetLength(0) == objTo.GetLength(0) &&
                objFrom.GetLength(1) == objTo.GetLength(1))
            {
                Array.Copy(objFrom, objTo, objFrom.Length);
                return(objTo);
            }

            if (!isDeep)
            {
                for (var i = 0; i < l1; i++)
                {
                    for (var k = 0; k < l2; k++)
                    {
                        objTo[i, k] = objFrom[i, k];
                    }
                }
                return(objTo);
            }

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

            return(objTo);
        }
Пример #9
0
        // rare cases, very slow cloning. currently it's ok
        internal static Array CloneAbstractArrayInternal(Array objFrom, Array objTo, DeepCloneState state, bool isDeep)
        {
            // not null from called method, but will check it anyway
            if (objFrom == null || objTo == null)
            {
                return(null);
            }
            var rank = objFrom.Rank;

            if (objTo.Rank != rank)
            {
                throw new InvalidOperationException("Invalid rank of target array");
            }
            var lowerBoundsFrom = Enumerable.Range(0, rank).Select(objFrom.GetLowerBound).ToArray();
            var lowerBoundsTo   = Enumerable.Range(0, rank).Select(objTo.GetLowerBound).ToArray();
            var lengths         = Enumerable.Range(0, rank).Select(x => Math.Min(objFrom.GetLength(x), objTo.GetLength(x))).ToArray();
            var idxesFrom       = Enumerable.Range(0, rank).Select(objFrom.GetLowerBound).ToArray();
            var idxesTo         = Enumerable.Range(0, rank).Select(objTo.GetLowerBound).ToArray();

            state.AddKnownRef(objFrom, objTo);
            while (true)
            {
                if (isDeep)
                {
                    objTo.SetValue(DeepClonerGenerator.CloneClassInternal(objFrom.GetValue(idxesFrom), state), idxesTo);
                }
                else
                {
                    objTo.SetValue(objFrom.GetValue(idxesFrom), idxesTo);
                }
                var ofs = rank - 1;
                while (true)
                {
                    idxesFrom[ofs]++;
                    idxesTo[ofs]++;
                    if (idxesFrom[ofs] >= lowerBoundsFrom[ofs] + lengths[ofs])
                    {
                        idxesFrom[ofs] = lowerBoundsFrom[ofs];
                        idxesTo[ofs]   = lowerBoundsTo[ofs];
                        ofs--;
                        if (ofs < 0)
                        {
                            return(objTo);
                        }
                    }
                    else
                    {
                        break;
                    }
                }
            }
        }
Пример #10
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));
        }
Пример #11
0
        internal static T[] Clone1DimArrayClassInternal <T>(T[] objFrom, T[] objTo, DeepCloneState state)
        {
            if (objFrom == null || objTo == null)
            {
                return(null);
            }
            int num = Math.Min(objFrom.Length, objTo.Length);

            state.AddKnownRef(objFrom, objTo);
            for (int i = 0; i < num; i++)
            {
                objTo[i] = (T)DeepClonerGenerator.CloneClassInternal(objFrom[i], state);
            }
            return(objTo);
        }
Пример #12
0
        internal static Array CloneAbstractArrayInternal(Array objFrom, Array objTo, DeepCloneState state, bool isDeep)
        {
            if (objFrom == null || objTo == null)
            {
                return(null);
            }
            int rank = objFrom.Rank;

            if (objTo.Rank == rank)
            {
                int[] array  = Enumerable.Range(0, rank).Select(objFrom.GetLowerBound).ToArray();
                int[] array2 = Enumerable.Range(0, rank).Select(objTo.GetLowerBound).ToArray();
                int[] array3 = (from x in Enumerable.Range(0, rank)
                                select Math.Min(objFrom.GetLength(x), objTo.GetLength(x))).ToArray();
                int[] array4 = Enumerable.Range(0, rank).Select(objFrom.GetLowerBound).ToArray();
                int[] array5 = Enumerable.Range(0, rank).Select(objTo.GetLowerBound).ToArray();
                state.AddKnownRef(objFrom, objTo);
                while (true)
                {
                    if (isDeep)
                    {
                        objTo.SetValue(DeepClonerGenerator.CloneClassInternal(objFrom.GetValue(array4), state), array5);
                    }
                    else
                    {
                        objTo.SetValue(objFrom.GetValue(array4), array5);
                    }
                    int num = rank - 1;
                    while (true)
                    {
                        array4[num]++;
                        array5[num]++;
                        if (array4[num] < array[num] + array3[num])
                        {
                            break;
                        }
                        array4[num] = array[num];
                        array5[num] = array2[num];
                        num--;
                        if (num < 0)
                        {
                            return(objTo);
                        }
                    }
                }
            }
            throw new InvalidOperationException("Invalid rank of target array");
        }
Пример #13
0
        internal static T[] Clone1DimArrayClassInternal <T>(T[] obj, DeepCloneState state)
        {
            if (obj == null)
            {
                return(null);
            }
            int num = obj.Length;

            T[] array = new T[num];
            state.AddKnownRef(obj, array);
            for (int i = 0; i < num; i++)
            {
                array[i] = (T)CloneClassInternal(obj[i], state);
            }
            return(array);
        }
Пример #14
0
        internal static T[,] Clone2DimArrayInternal <T>(T[,] obj, DeepCloneState state)
        {
            if (obj == null)
            {
                return(null);
            }
            int length  = obj.GetLength(0);
            int length2 = obj.GetLength(1);

            T[,] array = new T[length, length2];
            state.AddKnownRef(obj, array);
            if (DeepClonerSafeTypes.CanNotCopyType(typeof(T), null))
            {
                Array.Copy(obj, array, obj.Length);
                return(array);
            }
            if (typeof(T).IsValueType())
            {
                Func <T, DeepCloneState, T> clonerForValueType = GetClonerForValueType <T>();
                for (int i = 0; i < length; i++)
                {
                    for (int j = 0; j < length2; j++)
                    {
                        T[,] array2 = array;
                        int num  = i;
                        int num2 = j;
                        T   val  = clonerForValueType(obj[i, j], state);
                        array2[num, num2] = val;
                    }
                }
            }
            else
            {
                for (int k = 0; k < length; k++)
                {
                    for (int l = 0; l < length2; l++)
                    {
                        T[,] array3 = array;
                        int num3 = k;
                        int num4 = l;
                        T   obj2 = (T)CloneClassInternal(obj[k, l], state);
                        array3[num3, num4] = obj2;
                    }
                }
            }
            return(array);
        }
Пример #15
0
        internal static T[] Clone1DimArrayClassInternal <T>(T[] objFrom, T[] objTo, DeepCloneState state)
        {
            // not null from called method, but will check it anyway
            if (objFrom == null || objTo == null)
            {
                return(null);
            }
            var l = Math.Min(objFrom.Length, objTo.Length);

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

            return(objTo);
        }
Пример #16
0
        internal static T[] Clone1DimArrayStructInternal <T>(T[] objFrom, T[] objTo, DeepCloneState state)
        {
            if (objFrom == null || objTo == null)
            {
                return(null);
            }
            int num = Math.Min(objFrom.Length, objTo.Length);

            state.AddKnownRef(objFrom, objTo);
            Func <T, DeepCloneState, T> clonerForValueType = DeepClonerGenerator.GetClonerForValueType <T>();

            for (int i = 0; i < num; i++)
            {
                objTo[i] = clonerForValueType(objTo[i], state);
            }
            return(objTo);
        }
Пример #17
0
        internal static T[] Clone1DimArrayStructInternal <T>(T[] obj, DeepCloneState state)
        {
            if (obj == null)
            {
                return(null);
            }
            int num = obj.Length;

            T[] array = new T[num];
            state.AddKnownRef(obj, array);
            Func <T, DeepCloneState, T> clonerForValueType = GetClonerForValueType <T>();

            for (int i = 0; i < num; i++)
            {
                array[i] = clonerForValueType(obj[i], state);
            }
            return(array);
        }
Пример #18
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);
        }
Пример #19
0
        internal static T[] Clone1DimArrayStructInternal <T>(T[] objFrom, T[] objTo, DeepCloneState state)
        {
            // not null from called method, but will check it anyway
            if (objFrom == null || objTo == null)
            {
                return(null);
            }
            var l = Math.Min(objFrom.Length, objTo.Length);

            state.AddKnownRef(objFrom, objTo);
            var cloner = DeepClonerGenerator.GetClonerForValueType <T>();

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

            return(objTo);
        }
Пример #20
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.IsTypeSafe(typeof(T), null))
            {
                Array.Copy(obj, outArray, obj.Length);
                return(outArray);
            }

            if (typeof(T).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);
        }
Пример #21
0
        internal static object CloneClassInternal(object obj, DeepCloneState state)
        {
            if (obj == null)
            {
                return(null);
            }
            Func <object, DeepCloneState, object> func = (Func <object, DeepCloneState, object>)DeepClonerCache.GetOrAddClass(obj.GetType(), (Type t) => GenerateCloner(t, true));

            if (func == null)
            {
                return(obj);
            }
            object knownRef = state.GetKnownRef(obj);

            if (knownRef != null)
            {
                return(knownRef);
            }
            return(func(obj, state));
        }
Пример #22
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);
        }
Пример #23
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;
                    }
                }
            }
        }