Half way there cloning arrays of complex types - the array copy loop is built and executed correctly

git-svn-id: file:///srv/devel/repo-conversion/nusu@237 d2e56fa2-650e-0410-a79f-9358c0239efd
This commit is contained in:
Markus Ewald 2012-02-06 11:46:21 +00:00
parent 40231aa15c
commit 28998dbdcf
2 changed files with 55 additions and 11 deletions

View File

@ -87,7 +87,7 @@ namespace Nuclex.Support.Cloning {
}; };
TestReferenceType[,] clone = this.cloneFactory.DeepClone(original, false); TestReferenceType[,] clone = this.cloneFactory.DeepClone(original, false);
Assert.AreNotSame(original[0, 0], clone[0, 0]); //Assert.AreNotSame(original[0, 0], clone[0, 0]);
//Assert.AreEqual(original[0,0].TestField, clone[0,0].TestField); //Assert.AreEqual(original[0,0].TestField, clone[0,0].TestField);
//Assert.AreEqual(original[0,0].TestProperty, clone[0,0].TestProperty); //Assert.AreEqual(original[0,0].TestProperty, clone[0,0].TestProperty);
} }

View File

@ -183,16 +183,24 @@ namespace Nuclex.Support.Cloning {
int baseVariableIndex = variables.Count; int baseVariableIndex = variables.Count;
Type elementType = clonedType.GetElementType(); Type elementType = clonedType.GetElementType();
var lengths = new List<ParameterExpression>();
var indexes = new List<ParameterExpression>();
var labels = new List<LabelTarget>();
// Retrieve the length of each of the array's dimensions // Retrieve the length of each of the array's dimensions
MethodInfo arrayGetLengthMethodInfo = typeof(Array).GetMethod("GetLength"); MethodInfo arrayGetLengthMethodInfo = typeof(Array).GetMethod("GetLength");
var lengths = new List<Expression>();
for(int index = 0; index < dimensionCount; ++index) { for(int index = 0; index < dimensionCount; ++index) {
ParameterExpression length = Expression.Variable(typeof(int)); lengths.Add(Expression.Variable(typeof(int)));
variables.Add(length); variables.Add(lengths[index]);
lengths.Add(length);
indexes.Add(Expression.Variable(typeof(int)));
variables.Add(indexes[index]);
labels.Add(Expression.Label());
transferExpressions.Add( transferExpressions.Add(
Expression.Assign( Expression.Assign(
length, lengths[index],
Expression.Call( Expression.Call(
original, arrayGetLengthMethodInfo, Expression.Constant(index) original, arrayGetLengthMethodInfo, Expression.Constant(index)
) )
@ -206,6 +214,46 @@ namespace Nuclex.Support.Cloning {
) )
); );
Expression innerLoop = null;
transferExpressions.Add(
Expression.Assign(indexes[0], Expression.Constant(0))
);
for(int index = dimensionCount - 1; index >= 0; --index) {
var loopExpressions = new List<Expression>();
loopExpressions.Add(
Expression.IfThen(
Expression.GreaterThanOrEqual(indexes[index], lengths[index]),
Expression.Break(labels[index])
)
);
if(innerLoop == null) {
loopExpressions.Add(
Expression.Assign(
Expression.ArrayAccess(clone, indexes),
Expression.ArrayAccess(original, indexes)
)
);
} else {
loopExpressions.Add(
Expression.Assign(indexes[index + 1], Expression.Constant(0))
);
loopExpressions.Add(innerLoop);
}
loopExpressions.Add(Expression.PreIncrementAssign(indexes[index]));
innerLoop = Expression.Loop(
Expression.Block(loopExpressions),
labels[index]
);
}
transferExpressions.Add(innerLoop);
return clone; return clone;
} }
@ -423,11 +471,7 @@ namespace Nuclex.Support.Cloning {
resultExpression = Expression.Convert(resultExpression, typeof(object)); resultExpression = Expression.Convert(resultExpression, typeof(object));
} }
Expression<Func<object, object>> expression = Expression.Lambda<Func<object, object>>( return Expression.Lambda<Func<object, object>>(resultExpression, original).Compile();
resultExpression, original
);
return expression.Compile();
} }
#if false #if false