コード例 #1
0
ファイル: ArrayCloner.cs プロジェクト: nowol/DesertOctopus
        private static IEnumerable <Expression> PopulateDimensionalArrayLength(ParameterExpression sourceArray,
                                                                               ParameterExpression i,
                                                                               ParameterExpression lengths,
                                                                               int rank)
        {
            var loopExpressions = new List <Expression>();
            var expressions     = new List <Expression>();

            expressions.Add(Expression.Assign(i, Expression.Constant(0)));

            var length = Expression.Call(sourceArray, ArrayMih.GetLength(), i);

            loopExpressions.Add(Expression.Assign(Expression.ArrayAccess(lengths, i), length));
            loopExpressions.Add(Expression.Assign(i, Expression.Add(i, Expression.Constant(1))));

            var loopBody   = Expression.Block(loopExpressions);
            var breakLabel = Expression.Label("breakLabelLength");
            var cond       = Expression.LessThan(i, Expression.Constant(rank));
            var loop       = Expression.Loop(Expression.IfThenElse(cond,
                                                                   loopBody,
                                                                   Expression.Break(breakLabel)),
                                             breakLabel);

            expressions.Add(loop);

            return(expressions);
        }
コード例 #2
0
        private static IEnumerable <Expression> WriteDimensionalArrayLength(ParameterExpression outputStream,
                                                                            Expression objTracking,
                                                                            Expression i,
                                                                            ParameterExpression arr,
                                                                            ParameterExpression lengths,
                                                                            int rank)
        {
            var expressions = new List <Expression>();

            expressions.Add(PrimitiveHelpers.WriteByte(outputStream, Expression.Constant((byte)rank), objTracking));

            var loopExpressions = new List <Expression>();

            expressions.Add(Expression.Assign(i, Expression.Constant(0)));

            var length = Expression.Call(arr, ArrayMih.GetLength(), i);

            loopExpressions.Add(Expression.Assign(Expression.ArrayAccess(lengths, i), length));
            loopExpressions.Add(PrimitiveHelpers.WriteInt32(outputStream, Expression.ArrayIndex(lengths, i), objTracking));
            loopExpressions.Add(Expression.Assign(i, Expression.Add(i, Expression.Constant(1))));

            var loopBody   = Expression.Block(loopExpressions);
            var breakLabel = Expression.Label("breakLabel");
            var cond       = Expression.LessThan(i, Expression.Constant(rank));
            var loop       = Expression.Loop(Expression.IfThenElse(cond,
                                                                   loopBody,
                                                                   Expression.Break(breakLabel)),
                                             breakLabel);

            expressions.Add(loop);

            return(expressions);
        }
コード例 #3
0
ファイル: ArrayCloner.cs プロジェクト: nowol/DesertOctopus
        private static Expression GenerateJaggedArray(List <ParameterExpression> variables,
                                                      ParameterExpression source,
                                                      ParameterExpression clone,
                                                      Type sourceType,
                                                      ParameterExpression refTrackerParam)
        {
            var elementType = sourceType.GetElementType();

            var item       = Expression.Parameter(elementType, "item");
            var clonedItem = Expression.Parameter(elementType, "item");
            var typeExpr   = Expression.Parameter(typeof(Type), "typeExpr");
            var i          = Expression.Parameter(typeof(int), "i");
            var length     = Expression.Parameter(typeof(int), "length");

            variables.Add(typeExpr);
            variables.Add(clonedItem);
            variables.Add(item);
            variables.Add(length);
            variables.Add(i);

            var notTrackedExpressions = new List <Expression>();

            notTrackedExpressions.Add(Expression.Assign(length, Expression.Property(source, "Length")));
            notTrackedExpressions.Add(Expression.Assign(i, Expression.Constant(0)));
            notTrackedExpressions.Add(Expression.Assign(clone, Expression.Convert(Expression.New(sourceType.GetConstructor(new[] { typeof(int) }), length), sourceType)));
            notTrackedExpressions.Add(Expression.Call(refTrackerParam, ObjectClonerReferenceTrackerMih.Track(), source, clone));

            Debug.Assert(!elementType.IsPrimitive && !elementType.IsValueType && elementType != typeof(string), "Element type cannot be a primitive type");

            var loopExpressions = new List <Expression>();

            loopExpressions.Add(Expression.Assign(item, Expression.Convert(Expression.Call(source, ArrayMih.GetValue(), i), elementType)));
            loopExpressions.Add(ClassCloner.GetCloneClassTypeExpression(refTrackerParam, item, clonedItem, elementType));
            loopExpressions.Add(Expression.Call(clone, ArrayMih.SetValue(), Expression.Convert(clonedItem, typeof(object)), i));
            loopExpressions.Add(Expression.Assign(i, Expression.Add(i, Expression.Constant(1))));

            var cond     = Expression.LessThan(i, length);
            var loopBody = Expression.Block(loopExpressions);

            var breakLabel = Expression.Label("breakLabel");
            var loop       = Expression.Loop(Expression.IfThenElse(cond,
                                                                   loopBody,
                                                                   Expression.Break(breakLabel)),
                                             breakLabel);

            notTrackedExpressions.Add(loop);

            return(ObjectCloner.GenerateNullTrackedOrUntrackedExpression(source,
                                                                         clone,
                                                                         sourceType,
                                                                         refTrackerParam,
                                                                         Expression.Block(notTrackedExpressions)));
        }
コード例 #4
0
        private static IEnumerable <Expression> ReadJaggedArray(Type type,
                                                                Type elementType,
                                                                ParameterExpression newInstance,
                                                                List <ParameterExpression> variables,
                                                                ParameterExpression inputStream,
                                                                ParameterExpression objTracker)
        {
            var i            = Expression.Parameter(typeof(int), "i");
            var length       = Expression.Parameter(typeof(int), "length");
            var item         = Expression.Parameter(type.GetElementType(), "item");
            var typeName     = Expression.Parameter(typeof(string), "typeName");
            var typeExpr     = Expression.Parameter(typeof(TypeWithHashCode), "type");
            var typeHashCode = Expression.Parameter(typeof(int), "typeHashCode");
            var tmpValue     = Expression.Parameter(elementType, "tmpValue");
            var deserializer = Expression.Parameter(typeof(Func <Stream, DeserializerObjectTracker, object>), "deserializer");

            variables.Add(length);
            variables.Add(item);
            variables.Add(typeName);
            variables.Add(typeExpr);
            variables.Add(typeHashCode);
            variables.Add(i);
            variables.Add(tmpValue);
            variables.Add(deserializer);

            var expressions = new List <Expression>();

            expressions.Add(Expression.Assign(length, PrimitiveHelpers.ReadInt32(inputStream, objTracker)));
            expressions.Add(Expression.Assign(i, Expression.Constant(0)));
            expressions.Add(Expression.Assign(newInstance, Expression.Convert(Expression.New(type.GetConstructor(new[] { typeof(int) }), length), type)));
            if (type.IsClass)
            {
                expressions.Add(Expression.Call(objTracker, DeserializerObjectTrackerMih.TrackedObject(), newInstance));
            }

            var loopExpressions = new List <Expression>();

            loopExpressions.Add(Deserializer.GetReadClassExpression(inputStream, objTracker, tmpValue, typeExpr, typeName, typeHashCode, deserializer, elementType));
            loopExpressions.Add(Expression.Call(newInstance, ArrayMih.SetValue(), Expression.Convert(tmpValue, typeof(object)), i));
            loopExpressions.Add(Expression.Assign(i, Expression.Add(i, Expression.Constant(1))));

            var cond       = Expression.LessThan(i, length);
            var loopBody   = Expression.Block(loopExpressions);
            var breakLabel = Expression.Label("breakLabel");
            var loop       = Expression.Loop(Expression.IfThenElse(cond,
                                                                   loopBody,
                                                                   Expression.Break(breakLabel)),
                                             breakLabel);

            expressions.Add(loop);
            return(expressions);
        }
コード例 #5
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);
        }
コード例 #6
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);
        }
コード例 #7
0
ファイル: ArrayCloner.cs プロジェクト: nowol/DesertOctopus
        private static Expression GenerateArrayOfKnownDimension(List <ParameterExpression> variables,
                                                                ParameterExpression source,
                                                                ParameterExpression clone,
                                                                Type sourceType,
                                                                Type elementType,
                                                                ParameterExpression refTrackerParam)
        {
            var i       = Expression.Parameter(typeof(int), "i");
            var lengths = Expression.Parameter(typeof(int[]), "lengths");
            var rank    = sourceType.GetArrayRank();

            variables.Add(i);
            variables.Add(lengths);

            List <Expression> notTrackedExpressions = new List <Expression>();

            notTrackedExpressions.Add(Expression.IfThen(Expression.GreaterThanOrEqual(Expression.Constant(rank), Expression.Constant(255)),
                                                        Expression.Throw(Expression.New(NotSupportedExceptionMih.ConstructorString(), Expression.Constant("Array with more than 255 dimensions are not supported")))));
            notTrackedExpressions.Add(Expression.Assign(lengths, Expression.Call(CreateArrayMethodInfo.GetCreateArrayMethodInfo(typeof(int)), Expression.Constant(rank))));
            notTrackedExpressions.AddRange(PopulateDimensionalArrayLength(source, i, lengths, rank));
            notTrackedExpressions.Add(Expression.Assign(clone, Expression.Convert(Expression.Call(ArrayMih.CreateInstance(), Expression.Constant(elementType), lengths), sourceType)));
            notTrackedExpressions.Add(Expression.Call(refTrackerParam, ObjectClonerReferenceTrackerMih.Track(), source, clone));
            notTrackedExpressions.AddRange(GenerateCopyDimensionalArray(source, clone, sourceType, variables, lengths, rank, refTrackerParam));

            return(ObjectCloner.GenerateNullTrackedOrUntrackedExpression(source,
                                                                         clone,
                                                                         sourceType,
                                                                         refTrackerParam,
                                                                         Expression.Block(notTrackedExpressions)));
        }
コード例 #8
0
ファイル: ArrayCloner.cs プロジェクト: nowol/DesertOctopus
        /// <summary>
        /// Generate an expression tree for arrays
        /// </summary>
        /// <param name="variables">Global variables for the expression tree</param>
        /// <param name="source">Source object</param>
        /// <param name="clone">Clone object</param>
        /// <param name="sourceType">Type of the source object</param>
        /// <param name="refTrackerParam">Reference tracker</param>
        /// <returns>Expression tree to clone arrays</returns>
        public static Expression GenerateArrayExpression(List <ParameterExpression> variables,
                                                         ParameterExpression source,
                                                         ParameterExpression clone,
                                                         Type sourceType,
                                                         ParameterExpression refTrackerParam)
        {
            var elementType = sourceType.GetElementType();

            if (elementType.IsPrimitive || elementType.IsValueType || (elementType == typeof(string)))
            {
                return(Expression.Block(Expression.Assign(clone, Expression.Convert(Expression.Call(Expression.Convert(source, typeof(Array)), ArrayMih.Clone()), sourceType)),
                                        Expression.Call(refTrackerParam, ObjectClonerReferenceTrackerMih.Track(), source, clone)));
            }

            if (elementType.IsArray)
            {
                return(GenerateJaggedArray(variables, source, clone, sourceType, refTrackerParam));
            }
            else
            {
                return(GenerateArrayOfKnownDimension(variables, source, clone, sourceType, elementType, refTrackerParam));
            }
        }
コード例 #9
0
        private static IEnumerable <Expression> WriteJaggedArray(Type elementType,
                                                                 List <ParameterExpression> variables,
                                                                 ParameterExpression outputStream,
                                                                 ParameterExpression arr,
                                                                 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 i          = Expression.Parameter(typeof(int), "i");
            var length     = Expression.Parameter(typeof(int), "length");

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

            var expressions = new List <Expression>();

            expressions.Add(Expression.Assign(length, Expression.Property(arr, "Length")));
            expressions.Add(PrimitiveHelpers.WriteInt32(outputStream, length, objTracking));
            expressions.Add(Expression.Assign(i, Expression.Constant(0)));

            Debug.Assert(!elementType.IsPrimitive && !elementType.IsValueType && elementType != typeof(string), "Type cannot be a primitive");

            var loopExpressions = new List <Expression>();

            loopExpressions.Add(Expression.Assign(item, Expression.ArrayAccess(arr, i)));   // uh?
            loopExpressions.Add(Expression.Assign(item, Expression.Convert(Expression.Call(arr, ArrayMih.GetValue(), i), elementType)));
            loopExpressions.Add(Serializer.GetWriteClassTypeExpression(outputStream, objTracking, item, itemAsObj, typeExpr, serializer, elementType));
            loopExpressions.Add(Expression.Assign(i, Expression.Add(i, Expression.Constant(1))));

            var cond     = Expression.LessThan(i, length);
            var loopBody = Expression.Block(loopExpressions);

            var breakLabel = Expression.Label("breakLabel");
            var loop       = Expression.Loop(Expression.IfThenElse(cond,
                                                                   loopBody,
                                                                   Expression.Break(breakLabel)),
                                             breakLabel);

            expressions.Add(loop);

            return(expressions);
        }
コード例 #10
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);
        }