Пример #1
0
        private Expression CreateDeepCopyRectangulerArrayExpression(
            Type type,
            Type elementType,
            Expression source,
            Expression destination,
            Expression cache)
        {
            int rank    = type.GetArrayRank();
            var indexes = Enumerable.Range(0, rank)
                          .Select(x => Expression.Parameter(typeof(int), $"i{x}"))
                          .ToArray();

            var lengths = Enumerable.Range(0, rank)
                          .Select(x => ExpressionUtils.GetArrayLength(source, x))
                          .ToArray();

            var arrayAssign = Expression.Assign(
                destination,
                Expression.NewArrayBounds(elementType, lengths));

            var elementAssign = elementType.IsArray
                ? Build(
                TypeUtils.IsValueType(elementType.GetElementType())
                        ? CopyPolicy.ShallowCopy : CopyPolicy.DeepCopy,
                elementType,
                Expression.ArrayIndex(source, indexes),
                Expression.ArrayAccess(destination, indexes),
                cache)
                : ClassCloner.Instance.Build(
                elementType,
                Expression.ArrayIndex(source, indexes),
                Expression.ArrayAccess(destination, indexes),
                cache);

            Expression Loop(int rankIndex)
            {
                var endLoop = Expression.Label($"EndLoop{rankIndex}");

                return(Expression.Block(
                           Expression.Assign(indexes[rankIndex], ExpressionUtils.Zero),
                           Expression.Loop(
                               Expression.Block(
                                   Expression.IfThen(
                                       Expression.GreaterThanOrEqual(indexes[rankIndex], lengths[rankIndex]),
                                       Expression.Break(endLoop)),
                                   rankIndex < rank - 1 ? Loop(rankIndex + 1) : elementAssign,
                                   Expression.PreIncrementAssign(indexes[rankIndex])),
                               endLoop)));
            }

            return(Expression.Block(
                       indexes,
                       indexes.Select(i => Expression.Assign(i, ExpressionUtils.Zero))
                       .Concat(new[] { arrayAssign, Loop(0) })));
        }