public MethodInfos() { GetUninitializedObject = GetFuncCall(() => FormatterServices.GetUninitializedObject(typeof(int))); GetTypeFromHandle = GetFuncCall(() => Type.GetTypeFromHandle(typeof(Type).TypeHandle)); CopyInner = GetFuncCall(() => DeepCopier.Copy(default(object), default(CopyContext))).GetGenericMethodDefinition(); TryGetCopy = typeof(CopyContext).GetMethod("TryGetCopy"); RecordObject = GetActionCall((CopyContext ctx) => ctx.RecordCopy(default(object), default(object))); CopyArrayRank1Shallow = GetFuncCall(() => ArrayCopier.CopyArrayRank1Shallow(default(object[]), default(CopyContext))).GetGenericMethodDefinition(); CopyArrayRank1 = GetFuncCall(() => ArrayCopier.CopyArrayRank1(default(object[]), default(CopyContext))).GetGenericMethodDefinition(); CopyArrayRank2Shallow = GetFuncCall(() => ArrayCopier.CopyArrayRank2Shallow(default(object[, ]), default(CopyContext))).GetGenericMethodDefinition(); CopyArrayRank2 = GetFuncCall(() => ArrayCopier.CopyArrayRank2(default(object[, ]), default(CopyContext))).GetGenericMethodDefinition(); MethodInfo GetActionCall <T>(Expression <Action <T> > expression) { return((expression.Body as MethodCallExpression)?.Method ?? throw new ArgumentException("Expression type unsupported.")); } MethodInfo GetFuncCall <T>(Expression <Func <T> > expression) { return((expression.Body as MethodCallExpression)?.Method ?? throw new ArgumentException("Expression type unsupported.")); } }
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); }
public MethodInfos() { this.GetUninitializedObject = GetFuncCall(() => FormatterServices.GetUninitializedObject(typeof(int))); this.GetTypeFromHandle = GetFuncCall(() => Type.GetTypeFromHandle(typeof(Type).TypeHandle)); this.CopyInner = GetFuncCall(() => DeepCopier.Copy(default(object), default(CopyContext))).GetGenericMethodDefinition(); this.RecordObject = GetActionCall((CopyContext ctx) => ctx.RecordCopy(default(object), default(object))); MethodInfo GetActionCall <T>(Expression <Action <T> > expression) { return((expression.Body as MethodCallExpression)?.Method ?? throw new ArgumentException("Expression type unsupported.")); } MethodInfo GetFuncCall <T>(Expression <Func <T> > expression) { return((expression.Body as MethodCallExpression)?.Method ?? throw new ArgumentException("Expression type unsupported.")); } }