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 Func <EnumerableLoopBodyCargo, Expression> GetLoopBodyCargo(ParameterExpression siClone, ParameterExpression clonedItem, ParameterExpression refTrackerParam) { Func <EnumerableLoopBodyCargo, Expression> loopBody = cargo => { var keyExpression = Expression.Property(Expression.Property(cargo.Enumerator, cargo.EnumeratorType.GetProperty("Current")), cargo.KvpType.GetProperty("Name")); var valueExpression = Expression.Property(Expression.Property(cargo.Enumerator, cargo.EnumeratorType.GetProperty("Current")), cargo.KvpType.GetProperty("Value")); var cloneValueExpr = Expression.Block(ClassCloner.GetCloneClassTypeExpression(refTrackerParam, valueExpression, clonedItem, typeof(object)), Expression.Call(siClone, SerializationInfoMih.AddValue(), keyExpression, clonedItem)); return(Expression.IfThenElse(Expression.Equal(valueExpression, Expression.Constant(null)), Expression.Call(siClone, SerializationInfoMih.AddValue(), keyExpression, Expression.Constant((object)null, typeof(object))), cloneValueExpr)); }; return(loopBody); }
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); }