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); }
/// <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)); }
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); }
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); }
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); }
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); }
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); }
public static T Copy(T original, CopyContext context) { // ReSharper disable once ExpressionIsAlwaysNull if (original is null) { return(original); } var type = original.GetType(); if (type == GenericType) { return(MatchingTypeCopier(original, context)); } var result = Copiers.GetOrAdd(type, GenerateCopier); return(result(original, context)); }
/// <summary> /// Returns a copy of the provided array. /// </summary> /// <param name="originalArray">The original array.</param> /// <param name="context">The copy context.</param> /// <returns>A copy of the original array.</returns> private static object CopyArray(Array originalArray, CopyContext context) { // Special-case for empty rank-1 arrays. if (originalArray.Rank == 1 && originalArray.GetLength(0) == 0) { return(originalArray); } // Special-case for arrays of immutable types. var elementType = originalArray.GetType().GetElementType(); if (CopyPolicy.IsImmutable(elementType)) { return(originalArray.Clone()); } 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); switch (rank) { case 1: for (var i = 0; i < lengths[0]; i++) { copyArray.SetValue(Copy(originalArray.GetValue(i), context), i); } break; case 2: for (var i = 0; i < lengths[0]; i++) { for (var j = 0; j < lengths[1]; j++) { copyArray.SetValue(Copy(originalArray.GetValue(i, j), context), i, j); } } break; default: 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(Copy(originalArray.GetValue(index), context), index); } break; } return(copyArray); }
/// <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) { return(CopierGenerator <T> .Copy(original, context)); }