private static IEnumerable <Expression> ReadDimensionalArray(Type type, Type elementType, ParameterExpression newInstance, List <ParameterExpression> variables, ParameterExpression inputStream, ParameterExpression lengths, ParameterExpression objTracker, int rank) { var typeName = Expression.Parameter(typeof(string), "typeName"); var typeExpr = Expression.Parameter(typeof(TypeWithHashCode), "type"); var indices = Expression.Parameter(typeof(int[]), "indices"); var tmpValue = Expression.Parameter(elementType, "tmpValue"); var deserializer = Expression.Parameter(typeof(Func <Stream, DeserializerObjectTracker, object>), "deserializer"); var typeHashCode = Expression.Parameter(typeof(int), "typeHashCode"); variables.Add(deserializer); variables.Add(typeName); variables.Add(typeExpr); variables.Add(tmpValue); variables.Add(typeHashCode); var expressions = new List <Expression>(); expressions.Add(Expression.Assign(newInstance, Expression.Convert(Expression.Call(ArrayMih.CreateInstance(), Expression.Constant(elementType), lengths), type))); if (type.IsClass) { expressions.Add(Expression.Call(objTracker, DeserializerObjectTrackerMih.TrackedObject(), newInstance)); } if (rank > 1) { variables.Add(indices); expressions.Add(Expression.Assign(indices, Expression.Call(CreateArrayMethodInfo.GetCreateArrayMethodInfo(typeof(int)), Expression.Property(lengths, "Length")))); } Expression innerExpression; if (elementType == typeof(string)) { innerExpression = Expression.Assign(tmpValue, Deserializer.GenerateStringExpression(inputStream, objTracker)); } else if (elementType.IsPrimitive || elementType.IsValueType) { var primitiveReader = Deserializer.GetPrimitiveReader(elementType); if (primitiveReader == null) { var primitiveDeserializer = Deserializer.GetTypeDeserializer(elementType); innerExpression = Expression.Assign(tmpValue, Expression.Convert(Expression.Invoke(Expression.Constant(primitiveDeserializer), inputStream, objTracker), elementType)); } else { if (elementType == typeof(byte) || elementType == typeof(sbyte) || elementType == typeof(byte?) || elementType == typeof(sbyte?) || Deserializer.IsEnumOrNullableEnum(elementType)) { innerExpression = Expression.Assign(tmpValue, Expression.Convert(primitiveReader(inputStream, objTracker), elementType)); } else { innerExpression = Expression.Assign(tmpValue, primitiveReader(inputStream, objTracker)); } } } else { innerExpression = Deserializer.GetReadClassExpression(inputStream, objTracker, tmpValue, typeExpr, typeName, typeHashCode, deserializer, elementType); } Func <int, Expression, Expression> readArrayLoop = (loopRank, innerExpr) => { var loopRankIndex = Expression.Parameter(typeof(int), "loopRankIndex" + loopRank); variables.Add(loopRankIndex); var loopExpressions = new List <Expression>(); if (rank == 1) { loopExpressions.Add(innerExpr); loopExpressions.Add(Expression.Assign(Expression.ArrayAccess(newInstance, loopRankIndex), tmpValue)); } else { loopExpressions.Add(Expression.Assign(Expression.ArrayAccess(indices, Expression.Constant(loopRank)), loopRankIndex)); loopExpressions.Add(innerExpr); loopExpressions.Add(Expression.Call(newInstance, ArrayMih.SetValueRank(), Expression.Convert(tmpValue, typeof(object)), indices)); } 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 = readArrayLoop(r, innerExpression); } expressions.Add(innerExpression); return(expressions); }
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); }