From e57140579c77d73c8c492e95bb9b5c15a2785257 Mon Sep 17 00:00:00 2001 From: Markus Ewald Date: Wed, 8 Feb 2012 11:05:07 +0000 Subject: [PATCH] Expression tree cloner now clones nested arrays in any depth (inline since deriving from an array is not possible, so it's pretty darn fast!), only scenario left open now is arrays of reference types git-svn-id: file:///srv/devel/repo-conversion/nusu@239 d2e56fa2-650e-0410-a79f-9358c0239efd --- Source/Cloning/ExpressionTreeCloner.cs | 83 +++++++++++++++++++++++--- 1 file changed, 75 insertions(+), 8 deletions(-) diff --git a/Source/Cloning/ExpressionTreeCloner.cs b/Source/Cloning/ExpressionTreeCloner.cs index 26d059a..158e7b1 100644 --- a/Source/Cloning/ExpressionTreeCloner.cs +++ b/Source/Cloning/ExpressionTreeCloner.cs @@ -229,6 +229,7 @@ namespace Nuclex.Support.Cloning { // Build the nested loops (one for each dimension) from the inside out Expression innerLoop = null; for(int index = dimensionCount - 1; index >= 0; --index) { + var loopVariables = new List(); var loopExpressions = new List(); // If we reached the end of the current array dimension, break the loop @@ -241,14 +242,80 @@ namespace Nuclex.Support.Cloning { if(innerLoop == null) { // The innermost loop clones an actual array element - - - loopExpressions.Add( - Expression.Assign( + if(elementType.IsPrimitive || (elementType == typeof(string))) { + loopExpressions.Add( + Expression.Assign( + Expression.ArrayAccess(clone, indexes), + Expression.ArrayAccess(original, indexes) + ) + ); + } else if(elementType.IsValueType) { + generateComplexTypeTransferExpressions( + elementType, + Expression.ArrayAccess(original, indexes), Expression.ArrayAccess(clone, indexes), - Expression.ArrayAccess(original, indexes) - ) - ); + variables, + loopExpressions + ); + } else { + ParameterExpression originalElement = Expression.Variable(elementType); + loopVariables.Add(originalElement); + + loopExpressions.Add( + Expression.Assign(originalElement, Expression.ArrayAccess(original, indexes)) + ); + + var nestedVariables = new List(); + var nestedTransferExpressions = new List(); + + if(elementType.IsArray) { + Expression clonedElement; + + Type nestedElementType = elementType.GetElementType(); + if(nestedElementType.IsPrimitive || (nestedElementType == typeof(string))) { + clonedElement = generatePrimitiveArrayTransferExpressions( + elementType, originalElement, nestedVariables, nestedTransferExpressions + ); + } else { + clonedElement = generateComplexArrayTransferExpressions( + elementType, originalElement, nestedVariables, nestedTransferExpressions + ); + } + nestedTransferExpressions.Add( + Expression.Assign(Expression.ArrayAccess(clone, indexes), clonedElement) + ); + } else { + ParameterExpression clonedElement = Expression.Variable(elementType); + loopVariables.Add(clonedElement); + + nestedTransferExpressions.Add( + Expression.Assign(clonedElement, originalElement) + ); + + //generateComplexTypeTransferExpressions( + // elementType, + // originalElement, + // clonedElement, + // loopVariables, + // loopExpressions + //); + + nestedTransferExpressions.Add( + Expression.Assign(Expression.ArrayAccess(clone, indexes), clonedElement) + ); + } + + loopExpressions.Add( + Expression.IfThen( + Expression.NotEqual(originalElement, Expression.Constant(null)), + Expression.Block( + nestedVariables, + nestedTransferExpressions + ) + ) + ); + } + } else { // Outer loops of any level just reset the inner loop's indexer and execute // the inner loop @@ -263,7 +330,7 @@ namespace Nuclex.Support.Cloning { // Build the loop using the expressions recorded above innerLoop = Expression.Loop( - Expression.Block(loopExpressions), + Expression.Block(loopVariables, loopExpressions), labels[index] ); }