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); }
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); }