Exemplo n.º 1
0
        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);
        }