コード例 #1
0
ファイル: ArrayCloner.cs プロジェクト: nowol/DesertOctopus
        private static IEnumerable <Expression> GenerateCopyDimensionalArray(ParameterExpression sourceArray,
                                                                             ParameterExpression cloneArray,
                                                                             Type sourceType,
                                                                             List <ParameterExpression> variables,
                                                                             ParameterExpression lengths,
                                                                             int rank,
                                                                             ParameterExpression refTrackerParam)
        {
            var elementType = sourceType.GetElementType();

            var item       = Expression.Parameter(elementType, "item");
            var clonedItem = Expression.Parameter(elementType, "clonedItem");
            var typeExpr   = Expression.Parameter(typeof(Type), "typeExpr");
            var indices    = Expression.Parameter(typeof(int[]), "indices");

            variables.Add(typeExpr);
            variables.Add(item);
            variables.Add(indices);
            variables.Add(clonedItem);

            var expressions = new List <Expression>();

            expressions.Add(Expression.Assign(indices, Expression.Call(CreateArrayMethodInfo.GetCreateArrayMethodInfo(typeof(int)), Expression.Constant(rank))));

            Debug.Assert(!(elementType.IsPrimitive || elementType.IsValueType || elementType == typeof(string)), "This method is not made to handle primitive types");

            Expression innerExpression = Expression.Block(ClassCloner.GetCloneClassTypeExpression(refTrackerParam, item, clonedItem, elementType),
                                                          Expression.Call(cloneArray, ArrayMih.SetValueRank(), Expression.Convert(clonedItem, typeof(object)), indices));

            Func <int, Expression, Expression> makeArrayLoop = (loopRank,
                                                                innerExpr) =>
            {
                var loopRankIndex = Expression.Parameter(typeof(int), "loopRankIndex" + loopRank);
                variables.Add(loopRankIndex);

                var loopExpressions = new List <Expression>();

                loopExpressions.Add(Expression.Assign(Expression.ArrayAccess(indices, Expression.Constant(loopRank)), loopRankIndex));
                loopExpressions.Add(Expression.Assign(item, Expression.Convert(Expression.Call(sourceArray, ArrayMih.GetValueRank(), indices), elementType)));
                loopExpressions.Add(innerExpr);
                loopExpressions.Add(Expression.Assign(loopRankIndex, Expression.Add(loopRankIndex, Expression.Constant(1))));

                var cond     = Expression.LessThan(loopRankIndex, Expression.ArrayIndex(lengths, Expression.Constant(loopRank)));
                var loopBody = Expression.Block(loopExpressions);

                var breakLabel = Expression.Label("breakLabel" + loopRank);
                var loop       = Expression.Loop(Expression.IfThenElse(cond,
                                                                       loopBody,
                                                                       Expression.Break(breakLabel)),
                                                 breakLabel);
                return(Expression.Block(Expression.Assign(loopRankIndex, Expression.Constant(0)),
                                        loop));
            };

            for (int r = rank - 1; r >= 0; r--)
            {
                innerExpression = makeArrayLoop(r, innerExpression);
            }

            expressions.Add(innerExpression);

            return(expressions);
        }
コード例 #2
0
        private static IEnumerable <Expression> WriteDimensionalArray(Type elementType,
                                                                      List <ParameterExpression> variables,
                                                                      ParameterExpression outputStream,
                                                                      ParameterExpression arr,
                                                                      int rank,
                                                                      ParameterExpression lengths,
                                                                      ParameterExpression objTracking)
        {
            var item       = Expression.Parameter(elementType, "item");
            var serializer = Expression.Parameter(typeof(Action <Stream, object, SerializerObjectTracker>), "serializer");
            var itemAsObj  = Expression.Parameter(typeof(object), "itemAsObj");
            var typeExpr   = Expression.Parameter(typeof(Type), "typeExpr");
            var indices    = Expression.Parameter(typeof(int[]), "indices");

            variables.Add(typeExpr);
            variables.Add(itemAsObj);
            variables.Add(serializer);
            variables.Add(item);

            var expressions = new List <Expression>();

            if (rank != 1)
            {
                variables.Add(indices);
                expressions.Add(Expression.Assign(indices, Expression.Call(CreateArrayMethodInfo.GetCreateArrayMethodInfo(typeof(int)), Expression.Constant(rank))));
            }

            Expression innerExpression;

            if (elementType == typeof(string))
            {
                innerExpression = Serializer.GenerateStringExpression(outputStream, item, objTracking);
            }
            else if (elementType.IsPrimitive || elementType.IsValueType)
            {
                var primitiveWriter = Serializer.GetPrimitiveWriter(elementType);

                if (primitiveWriter == null)
                {
                    var primitiveSerializer = Serializer.GetTypeSerializer(elementType);
                    innerExpression = Expression.Invoke(Expression.Constant(primitiveSerializer), outputStream, item, objTracking);
                }
                else
                {
                    innerExpression = primitiveWriter(outputStream, item, objTracking);
                }
            }
            else
            {
                innerExpression = Serializer.GetWriteClassTypeExpression(outputStream, objTracking, item, itemAsObj, typeExpr, serializer, elementType);
            }

            Func <int, Expression, Expression> makeArrayLoop = (loopRank,
                                                                innerExpr) =>
            {
                var loopRankIndex = Expression.Parameter(typeof(int), "loopRankIndex" + loopRank);
                variables.Add(loopRankIndex);

                var loopExpressions = new List <Expression>();

                if (rank == 1)
                {
                    loopExpressions.Add(Expression.Assign(item, Expression.ArrayAccess(arr, loopRankIndex)));
                }
                else
                {
                    loopExpressions.Add(Expression.Assign(Expression.ArrayAccess(indices, Expression.Constant(loopRank)), loopRankIndex));
                    loopExpressions.Add(Expression.Assign(item, Expression.Convert(Expression.Call(arr, ArrayMih.GetValueRank(), indices), elementType)));
                }

                loopExpressions.Add(innerExpr);
                loopExpressions.Add(Expression.Assign(loopRankIndex, Expression.Add(loopRankIndex, Expression.Constant(1))));

                var cond     = Expression.LessThan(loopRankIndex, Expression.ArrayIndex(lengths, Expression.Constant(loopRank)));
                var loopBody = Expression.Block(loopExpressions);

                var breakLabel = Expression.Label("breakLabel" + loopRank);
                var loop       = Expression.Loop(Expression.IfThenElse(cond,
                                                                       loopBody,
                                                                       Expression.Break(breakLabel)),
                                                 breakLabel);
                return(Expression.Block(Expression.Assign(loopRankIndex, Expression.Constant(0)),
                                        loop));
            };

            for (int r = rank - 1; r >= 0; r--)
            {
                innerExpression = makeArrayLoop(r, innerExpression);
            }

            expressions.Add(innerExpression);

            return(expressions);
        }