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
This commit is contained in:
Markus Ewald 2012-02-08 11:05:07 +00:00
parent b2e484673d
commit e57140579c

View File

@ -229,6 +229,7 @@ namespace Nuclex.Support.Cloning {
// Build the nested loops (one for each dimension) from the inside out // Build the nested loops (one for each dimension) from the inside out
Expression innerLoop = null; Expression innerLoop = null;
for(int index = dimensionCount - 1; index >= 0; --index) { for(int index = dimensionCount - 1; index >= 0; --index) {
var loopVariables = new List<ParameterExpression>();
var loopExpressions = new List<Expression>(); var loopExpressions = new List<Expression>();
// If we reached the end of the current array dimension, break the loop // If we reached the end of the current array dimension, break the loop
@ -241,14 +242,80 @@ namespace Nuclex.Support.Cloning {
if(innerLoop == null) { if(innerLoop == null) {
// The innermost loop clones an actual array element // The innermost loop clones an actual array element
if(elementType.IsPrimitive || (elementType == typeof(string))) {
loopExpressions.Add( loopExpressions.Add(
Expression.Assign( Expression.Assign(
Expression.ArrayAccess(clone, indexes), Expression.ArrayAccess(clone, indexes),
Expression.ArrayAccess(original, indexes) Expression.ArrayAccess(original, indexes)
) )
); );
} else if(elementType.IsValueType) {
generateComplexTypeTransferExpressions(
elementType,
Expression.ArrayAccess(original, indexes),
Expression.ArrayAccess(clone, 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<ParameterExpression>();
var nestedTransferExpressions = new List<Expression>();
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 { } else {
// Outer loops of any level just reset the inner loop's indexer and execute // Outer loops of any level just reset the inner loop's indexer and execute
// the inner loop // the inner loop
@ -263,7 +330,7 @@ namespace Nuclex.Support.Cloning {
// Build the loop using the expressions recorded above // Build the loop using the expressions recorded above
innerLoop = Expression.Loop( innerLoop = Expression.Loop(
Expression.Block(loopExpressions), Expression.Block(loopVariables, loopExpressions),
labels[index] labels[index]
); );
} }