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