diff --git a/Source/Cloning/ReflectionCloner.Test.cs b/Source/Cloning/ReflectionCloner.Test.cs
index 8ed684f..71c118d 100644
--- a/Source/Cloning/ReflectionCloner.Test.cs
+++ b/Source/Cloning/ReflectionCloner.Test.cs
@@ -76,6 +76,10 @@ namespace Nuclex.Support.Cloning {
       public TestReferenceType ReferenceTypeField;
       /// Reference type property for testing
       public TestReferenceType ReferenceTypeProperty { get; set; }
+      /// An array field of reference types
+      public TestReferenceType[,][] ReferenceTypeArrayField;
+      /// An array property of reference types
+      public TestReferenceType[,][] ReferenceTypeArrayProperty { get; set; }
 
     }
 
@@ -98,6 +102,10 @@ namespace Nuclex.Support.Cloning {
       public TestReferenceType ReferenceTypeField;
       /// Reference type property for testing
       public TestReferenceType ReferenceTypeProperty { get; set; }
+      /// An array field of reference types
+      public TestReferenceType[,][] ReferenceTypeArrayField;
+      /// An array property of reference types
+      public TestReferenceType[,][] ReferenceTypeArrayProperty { get; set; }
 
     }
 
@@ -399,6 +407,32 @@ namespace Nuclex.Support.Cloning {
       return new HierarchicalValueType() {
         TestField = 123,
         TestProperty = 321,
+        ReferenceTypeArrayField = new TestReferenceType[2, 4][] {
+          {
+            null, null, null, null
+          },
+          {
+            null, null, null,
+            new TestReferenceType[3] {
+              new TestReferenceType() { TestField = 101, TestProperty = 202 },
+              null,
+              new TestReferenceType() { TestField = 909, TestProperty = 808 }
+            }
+          },
+        },
+        ReferenceTypeArrayProperty = new TestReferenceType[2, 4][] {
+          {
+            null, null, null, null
+          },
+          {
+            null, null, null,
+            new TestReferenceType[3] {
+              new TestReferenceType() { TestField = 303, TestProperty = 404 },
+              null,
+              new TestReferenceType() { TestField = 707, TestProperty = 606 }
+            }
+          },
+        },
         ValueTypeField = new TestValueType() {
           TestField = 456,
           TestProperty = 654
@@ -424,6 +458,32 @@ namespace Nuclex.Support.Cloning {
       return new HierarchicalReferenceType() {
         TestField = 123,
         TestProperty = 321,
+        ReferenceTypeArrayField = new TestReferenceType[2, 4][] {
+          {
+            null, null, null, null
+          },
+          {
+            null, null, null,
+            new TestReferenceType[3] {
+              new TestReferenceType() { TestField = 101, TestProperty = 202 },
+              null,
+              new TestReferenceType() { TestField = 909, TestProperty = 808 }
+            }
+          },
+        },
+        ReferenceTypeArrayProperty = new TestReferenceType[2, 4][] {
+          {
+            null, null, null, null
+          },
+          {
+            null, null, null,
+            new TestReferenceType[3] {
+              new TestReferenceType() { TestField = 303, TestProperty = 404 },
+              null,
+              new TestReferenceType() { TestField = 707, TestProperty = 606 }
+            }
+          },
+        },
         ValueTypeField = new TestValueType() {
           TestField = 456,
           TestProperty = 654
diff --git a/Source/Cloning/ReflectionCloner.cs b/Source/Cloning/ReflectionCloner.cs
index b51d419..91e92e6 100644
--- a/Source/Cloning/ReflectionCloner.cs
+++ b/Source/Cloning/ReflectionCloner.cs
@@ -23,10 +23,8 @@ using System.Reflection;
 
 namespace Nuclex.Support.Cloning {
 
-  // TODO: Doesn't clone arrays yet
-
   /// Clones objects using reflection
-  public class ReflectionCloner : ICloneFactory, IStateCopier {
+  public class ReflectionCloner : ICloneFactory {
 
     /// 
     ///   Creates a shallow clone of the specified object, reusing any referenced objects
@@ -38,22 +36,23 @@ namespace Nuclex.Support.Cloning {
     /// 
     /// A shallow clone of the provided object
     public TCloned ShallowClone(TCloned objectToClone, bool usePropertyBasedClone) {
-      if(typeof(TCloned).IsValueType) {
-        TCloned clone = Activator.CreateInstance();
+      Type originalType = objectToClone.GetType();
+      if(originalType.IsPrimitive) {
+        return objectToClone; // Being value types, primitives are copied by default
+      } else if(originalType.IsArray) {
+        return (TCloned)shallowCloneArray(objectToClone);
+      } else if(originalType.IsValueType) {
         if(usePropertyBasedClone) {
-          shallowCopyValueTypePropertyBased(ref objectToClone, ref clone);
+          return (TCloned)shallowCloneComplexPropertyBased(objectToClone);
         } else {
-          shallowCopyValueTypeFieldBased(ref objectToClone, ref clone);
+          return objectToClone; // Value types can be copied directly
         }
-        return clone;
       } else {
-        TCloned clone = (TCloned)Activator.CreateInstance(objectToClone.GetType());
         if(usePropertyBasedClone) {
-          shallowCopyReferenceTypePropertyBased(objectToClone.GetType(), objectToClone, clone);
+          return (TCloned)shallowCloneComplexPropertyBased(objectToClone);
         } else {
-          shallowCopyReferenceTypeFieldBased(objectToClone.GetType(), objectToClone, clone);
+          return (TCloned)shallowCloneComplexFieldBased(objectToClone);
         }
-        return clone;
       }
     }
 
@@ -68,360 +67,296 @@ namespace Nuclex.Support.Cloning {
     /// 
     /// A deep clone of the provided object
     public TCloned DeepClone(TCloned objectToClone, bool usePropertyBasedClone) {
-      if(typeof(TCloned).IsValueType) {
-        TCloned clone = Activator.CreateInstance();
-        if(usePropertyBasedClone) {
-          deepCopyValueTypePropertyBased(ref objectToClone, ref clone);
-        } else {
-          deepCopyValueTypeFieldBased(ref objectToClone, ref clone);
-        }
-        return clone;
+      if(usePropertyBasedClone) {
+        return (TCloned)deepCloneSinglePropertyBased(objectToClone);
       } else {
-        TCloned clone = (TCloned)Activator.CreateInstance(objectToClone.GetType());
-        if(usePropertyBasedClone) {
-          deepCopyReferenceTypePropertyBased(objectToClone.GetType(), objectToClone, clone);
-        } else {
-          deepCopyReferenceTypeFieldBased(objectToClone.GetType(), objectToClone, clone);
-        }
-        return clone;
+        return (TCloned)deepCloneSingleFieldBased(objectToClone);
       }
     }
 
-    /// Transfers the state of one object into another
-    /// Type of the object whose sate will be transferred
-    /// Original instance the state will be taken from
-    /// Target instance the state will be written to
-    /// Whether to perform a property-based state copy
-    public void ShallowCopyState(TState original, TState target, bool propertyBased)
-      where TState : class {
-      if(propertyBased) {
-        shallowCopyReferenceTypePropertyBased(typeof(TState), original, target);
-      } else {
-        shallowCopyReferenceTypeFieldBased(typeof(TState), original, target);
-      }
-    }
+    /// Clones a complex type using field-based value transfer
+    /// Original instance that will be cloned
+    /// A clone of the original instance
+    private object shallowCloneComplexFieldBased(object original) {
+      Type originalType = original.GetType();
+      object clone = Activator.CreateInstance(originalType);
 
-    /// Transfers the state of one object into another
-    /// Type of the object whose sate will be transferred
-    /// Original instance the state will be taken from
-    /// Target instance the state will be written to
-    /// Whether to perform a property-based state copy
-    public void ShallowCopyState(
-      ref TState original, ref TState target, bool propertyBased
-    ) where TState : struct {
-      if(propertyBased) {
-        shallowCopyValueTypePropertyBased(ref original, ref target);
-      } else {
-        shallowCopyValueTypeFieldBased(ref original, ref target);
-      }
-    }
-
-    /// 
-    ///   Transfers the state of one object into another, creating clones of referenced objects
-    /// 
-    /// Type of the object whose sate will be transferred
-    /// Original instance the state will be taken from
-    /// Target instance the state will be written to
-    /// Whether to perform a property-based state copy
-    public void DeepCopyState(TState original, TState target, bool propertyBased)
-      where TState : class {
-      if(propertyBased) {
-        deepCopyReferenceTypePropertyBased(typeof(TState), original, target);
-      } else {
-        deepCopyReferenceTypeFieldBased(typeof(TState), original, target);
-      }
-    }
-
-    /// 
-    ///   Transfers the state of one object into another, creating clones of referenced objects
-    /// 
-    /// Type of the object whose sate will be transferred
-    /// Original instance the state will be taken from
-    /// Target instance the state will be written to
-    /// Whether to perform a property-based state copy
-    public void DeepCopyState(ref TState original, ref TState target, bool propertyBased)
-      where TState : struct {
-      if(propertyBased) {
-        deepCopyValueTypePropertyBased(ref original, ref target);
-      } else {
-        deepCopyValueTypeFieldBased(ref original, ref target);
-      }
-    }
-
-    /// Creates a field-based shallow copy of a reference type
-    /// Type the copy will be based upon
-    /// Original object that will be copied
-    /// Target object into which copied values will be written
-    private static void shallowCopyReferenceTypeFieldBased(
-      Type copiedType, object original, object target
-    ) {
-      FieldInfo[] fieldInfos = copiedType.GetFields(
+      FieldInfo[] fieldInfos = originalType.GetFields(
         BindingFlags.Public | BindingFlags.NonPublic |
         BindingFlags.Instance | BindingFlags.FlattenHierarchy
       );
       for(int index = 0; index < fieldInfos.Length; ++index) {
         FieldInfo fieldInfo = fieldInfos[index];
-        fieldInfo.SetValue(target, fieldInfo.GetValue(original));
+        object originalValue = fieldInfo.GetValue(original);
+        if(originalValue != null) {
+          // Everything's just directly assigned in a shallow clone
+          fieldInfo.SetValue(clone, originalValue);
+        }
       }
+
+      return clone;
     }
 
-    /// Creates a property-based shallow copy of a reference type
-    /// Type the copy will be based upon
-    /// Original object that will be copied
-    /// Target object into which copied values will be written
-    private static void shallowCopyReferenceTypePropertyBased(
-      Type copiedType, object original, object target
-    ) {
-      PropertyInfo[] propertyInfos = copiedType.GetProperties(
+    /// Clones a complex type using property-based value transfer
+    /// Original instance that will be cloned
+    /// A clone of the original instance
+    private object shallowCloneComplexPropertyBased(object original) {
+      Type originalType = original.GetType();
+      object clone = Activator.CreateInstance(originalType);
+
+      PropertyInfo[] propertyInfos = originalType.GetProperties(
         BindingFlags.Public | BindingFlags.NonPublic |
         BindingFlags.Instance | BindingFlags.FlattenHierarchy
       );
       for(int index = 0; index < propertyInfos.Length; ++index) {
         PropertyInfo propertyInfo = propertyInfos[index];
-        if(propertyInfo.CanRead && propertyInfo.CanWrite) {
-          if(propertyInfo.PropertyType.IsPrimitive) {
-            propertyInfo.SetValue(
-              target,
-              propertyInfo.GetValue(original, null),
-              null
-            );
-          } else if(propertyInfo.PropertyType.IsValueType) {
-            // Recurse into the value type - value types are seen as part of
-            // the outer type and a shallow copy does follow their hierarchy.
-            // This is equivalent to what would happen if you directly assign
-            // one value type to another.
-            object boxedOriginalValue = propertyInfo.GetValue(original, null);
-            Type originalType = boxedOriginalValue.GetType();
-            object boxedClonedValue = Activator.CreateInstance(originalType);
-            shallowCopyReferenceTypePropertyBased(
-              originalType, boxedOriginalValue, boxedClonedValue
-            );
-            propertyInfo.SetValue(target, boxedClonedValue, null);
-          } else {
-            propertyInfo.SetValue(
-              target,
-              propertyInfo.GetValue(original, null),
-              null
-            );
-          }
-        }
-      }
-    }
-
-    /// Creates a property-based shallow copy of a value type
-    /// Value type that will be copied
-    /// Original object that will be copied
-    /// Target object into which copied values will be written
-    private static void shallowCopyValueTypePropertyBased(
-      ref TState original, ref TState target
-    ) {
-      object boxedOriginal = original;
-      object boxedTarget = target;
-
-      PropertyInfo[] propertyInfos = typeof(TState).GetProperties(
-        BindingFlags.Public | BindingFlags.NonPublic |
-        BindingFlags.Instance | BindingFlags.FlattenHierarchy
-      );
-      for(int index = 0; index < propertyInfos.Length; ++index) {
-        PropertyInfo propertyInfo = propertyInfos[index];
-
-        if(propertyInfo.CanRead && propertyInfo.CanWrite) {
-          if(propertyInfo.PropertyType.IsPrimitive) {
-            propertyInfo.SetValue(
-              boxedTarget,
-              propertyInfo.GetValue(boxedOriginal, null),
-              null
-            );
-          } else if(propertyInfo.PropertyType.IsValueType) {
-            object boxedOriginalValue = propertyInfo.GetValue(original, null);
-            Type originalType = boxedOriginalValue.GetType();
-            object boxedClonedValue = Activator.CreateInstance(originalType);
-            deepCopyReferenceTypePropertyBased(
-              originalType, boxedOriginalValue, boxedClonedValue
-            );
-            propertyInfo.SetValue(boxedTarget, boxedClonedValue, null);
-          } else {
-            propertyInfo.SetValue(
-              boxedTarget,
-              propertyInfo.GetValue(boxedOriginal, null),
-              null
-            );
+        Type propertyType = propertyInfo.PropertyType;
+        object originalValue = propertyInfo.GetValue(original, null);
+        if(originalValue != null) {
+          if(propertyType.IsPrimitive) { // Primitive types can be assigned directly
+            propertyInfo.SetValue(clone, originalValue, null);
+          } else if(propertyType.IsValueType) {
+            // Value types are seen as part of the original type and are thus recursed into
+            propertyInfo.SetValue(clone, shallowCloneComplexPropertyBased(originalValue), null);
+          } else if(propertyType.IsArray) { // Arrays are assigned directly in a shallow clone
+            propertyInfo.SetValue(clone, originalValue, null);
+          } else { // Complex types are directly assigned without creating a copy
+            propertyInfo.SetValue(clone, originalValue, null);
           }
         }
       }
 
-      target = (TState)boxedTarget;
+      return clone;
     }
 
-    /// Creates a field-based shallow copy of a value type
-    /// Value type that will be copied
-    /// Original object that will be copied
-    /// Target object into which copied values will be written
-    private static void shallowCopyValueTypeFieldBased(
-      ref TState original, ref TState target
-    ) {
-      target = original; // hehe
+    /// Clones an array using field-based value transfer
+    /// Original array that will be cloned
+    /// A clone of the original array
+    private object shallowCloneArray(object original) {
+      return ((Array)original).Clone();
     }
 
-    /// Creates a field-based deep copy of a reference type
-    /// Type the copy will be based upon
-    /// Original object that will be copied
-    /// Target object into which copied values will be written
-    private static void deepCopyReferenceTypeFieldBased(
-      Type copiedType, object original, object target
-    ) {
-      FieldInfo[] fieldInfos = copiedType.GetFields(
+    /// Copies a single object using field-based value transfer
+    /// Original object that will be cloned
+    /// A clone of the original object
+    private static object deepCloneSingleFieldBased(object original) {
+      Type originalType = original.GetType();
+      if(originalType.IsPrimitive) {
+        return original; // Creates another box, does not reference boxed primitive
+      } else if(originalType.IsArray) {
+        return deepCloneArrayFieldBased((Array)original, originalType.GetElementType());
+      } else {
+        return deepCloneComplexFieldBased(original);
+      }
+    }
+
+    /// Clones a complex type using field-based value transfer
+    /// Original instance that will be cloned
+    /// A clone of the original instance
+    private static object deepCloneComplexFieldBased(object original) {
+      Type originalType = original.GetType();
+      object clone = Activator.CreateInstance(originalType);
+
+      FieldInfo[] fieldInfos = originalType.GetFields(
         BindingFlags.Public | BindingFlags.NonPublic |
         BindingFlags.Instance | BindingFlags.FlattenHierarchy
       );
       for(int index = 0; index < fieldInfos.Length; ++index) {
         FieldInfo fieldInfo = fieldInfos[index];
-        if(fieldInfo.FieldType.IsPrimitive) {
-          fieldInfo.SetValue(target, fieldInfo.GetValue(original));
-        } else if(fieldInfo.FieldType.IsValueType) {
-          object boxedOriginalValue = fieldInfo.GetValue(original);
-          Type originalType = boxedOriginalValue.GetType();
-          object boxedClonedValue = Activator.CreateInstance(originalType);
-          deepCopyReferenceTypeFieldBased(originalType, boxedOriginalValue, boxedClonedValue);
-          fieldInfo.SetValue(target, boxedClonedValue);
-        } else {
-          object originalValue = fieldInfo.GetValue(original);
-          if(originalValue != null) {
-            Type originalType = originalValue.GetType();
-            object clonedValue = Activator.CreateInstance(originalType);
-            deepCopyReferenceTypeFieldBased(originalType, originalValue, clonedValue);
-            fieldInfo.SetValue(target, clonedValue);
+        Type fieldType = fieldInfo.FieldType;
+        object originalValue = fieldInfo.GetValue(original);
+        if(originalValue != null) {
+          if(fieldType.IsPrimitive) { // Primitive types can be assigned directly
+            fieldInfo.SetValue(clone, originalValue);
+          } else if(fieldType.IsArray) { // Arrays need to be cloned element-by-element
+            fieldInfo.SetValue(
+              clone,
+              deepCloneArrayFieldBased((Array)originalValue, fieldType.GetElementType())
+            );
+          } else { // Complex types need to be cloned member-by-member
+            fieldInfo.SetValue(clone, deepCloneSingleFieldBased(originalValue));
           }
         }
       }
+
+      return clone;
     }
 
-    /// Creates a property-based deep copy of a reference type
-    /// Type the copy will be based upon
-    /// Original object that will be copied
-    /// Target object into which copied values will be written
-    private static void deepCopyReferenceTypePropertyBased(
-      Type copiedType, object original, object target
-    ) {
-      PropertyInfo[] propertyInfos = copiedType.GetProperties(
+    /// Clones an array using field-based value transfer
+    /// Original array that will be cloned
+    /// Type of elements the original array contains
+    /// A clone of the original array
+    private static object deepCloneArrayFieldBased(Array original, Type elementType) {
+      if(elementType.IsPrimitive) {
+        return original.Clone();
+      }
+
+      int dimensionCount = original.Rank;
+
+      // Find out the length of each of the array's dimensions, also calculate how
+      // many elements there are in the array in total.
+      var lengths = new int[dimensionCount];
+      int totalElementCount = 0;
+      for(int index = 0; index < dimensionCount; ++index) {
+        lengths[index] = original.GetLength(index);
+        if(index == 0) {
+          totalElementCount = lengths[index];
+        } else {
+          totalElementCount *= lengths[index];
+        }
+      }
+
+      // Knowing the number of dimensions and the length of each dimension, we can
+      // create another array of the exact same sizes.
+      Array clone = Array.CreateInstance(elementType, lengths);
+
+      // If this is a one-dimensional array (most common type), do an optimized copy
+      // directly specifying the indices
+      if(dimensionCount == 1) {
+
+        // Clone each element of the array directly
+        for(int index = 0; index < totalElementCount; ++index) {
+          object originalElement = original.GetValue(index);
+          if(originalElement != null) {
+            clone.SetValue(deepCloneSingleFieldBased(originalElement), index);
+          }
+        }
+
+      } else { // Otherwise use the generic code for multi-dimensional arrays
+
+        var indices = new int[dimensionCount];
+        for(int index = 0; index < totalElementCount; ++index) {
+
+          // Determine the index for each of the array's dimensions
+          int elementIndex = index;
+          for(int dimensionIndex = dimensionCount - 1; dimensionIndex >= 0; --dimensionIndex) {
+            indices[dimensionIndex] = elementIndex % lengths[dimensionIndex];
+            elementIndex /= lengths[dimensionIndex];
+          }
+
+          // Clone the current array element
+          object originalElement = original.GetValue(indices);
+          if(originalElement != null) {
+            clone.SetValue(deepCloneSingleFieldBased(originalElement), indices);
+          }
+
+        }
+
+      }
+
+      return clone;
+    }
+
+    /// Copies a single object using property-based value transfer
+    /// Original object that will be cloned
+    /// A clone of the original object
+    private static object deepCloneSinglePropertyBased(object original) {
+      Type originalType = original.GetType();
+      if(originalType.IsPrimitive) {
+        return original; // Creates another box, does not reference boxed primitive
+      } else if(originalType.IsArray) {
+        return deepCloneArrayPropertyBased((Array)original, originalType.GetElementType());
+      } else {
+        return deepCloneComplexPropertyBased(original);
+      }
+    }
+
+    /// Clones a complex type using property-based value transfer
+    /// Original instance that will be cloned
+    /// A clone of the original instance
+    private static object deepCloneComplexPropertyBased(object original) {
+      Type originalType = original.GetType();
+      object clone = Activator.CreateInstance(originalType);
+
+      PropertyInfo[] propertyInfos = originalType.GetProperties(
         BindingFlags.Public | BindingFlags.NonPublic |
         BindingFlags.Instance | BindingFlags.FlattenHierarchy
       );
       for(int index = 0; index < propertyInfos.Length; ++index) {
         PropertyInfo propertyInfo = propertyInfos[index];
-        if(propertyInfo.CanRead && propertyInfo.CanWrite) {
-          if(propertyInfo.PropertyType.IsPrimitive) {
+        Type propertyType = propertyInfo.PropertyType;
+        object originalValue = propertyInfo.GetValue(original, null);
+        if(originalValue != null) {
+          if(propertyType.IsPrimitive) { // Primitive types can be assigned directly
+            propertyInfo.SetValue(clone, originalValue, null);
+          } else if(propertyType.IsArray) { // Arrays need to be cloned element-by-element
             propertyInfo.SetValue(
-              target,
-              propertyInfo.GetValue(original, null),
+              clone,
+              deepCloneArrayPropertyBased((Array)originalValue, propertyType.GetElementType()),
               null
             );
-          } else if(propertyInfo.PropertyType.IsValueType) {
-            object boxedOriginalValue = propertyInfo.GetValue(original, null);
-            Type originalType = boxedOriginalValue.GetType();
-            object boxedClonedValue = Activator.CreateInstance(originalType);
-            deepCopyReferenceTypePropertyBased(
-              originalType, boxedOriginalValue, boxedClonedValue
-            );
-            propertyInfo.SetValue(target, boxedClonedValue, null);
-          } else {
-            object originalValue = propertyInfo.GetValue(original, null);
-            if(originalValue != null) {
-              Type originalType = originalValue.GetType();
-              object clonedValue = Activator.CreateInstance(originalType);
-              deepCopyReferenceTypePropertyBased(
-                originalType, originalValue, clonedValue
-              );
-              propertyInfo.SetValue(target, clonedValue, null);
-            }
+          } else { // Complex types need to be cloned member-by-member
+            propertyInfo.SetValue(clone, deepCloneSinglePropertyBased(originalValue), null);
           }
         }
       }
+
+      return clone;
     }
 
-    /// Creates a field-based deep copy of a value type
-    /// Value type that will be copied
-    /// Original object that will be copied
-    /// Target object into which copied values will be written
-    private static void deepCopyValueTypeFieldBased(
-      ref TState original, ref TState target
-    ) {
-      object boxedOriginal = original;
-      object boxedTarget = Activator.CreateInstance(original.GetType());
+    /// Clones an array using property-based value transfer
+    /// Original array that will be cloned
+    /// Type of elements the original array contains
+    /// A clone of the original array
+    private static object deepCloneArrayPropertyBased(Array original, Type elementType) {
+      if(elementType.IsPrimitive) {
+        return original.Clone();
+      }
 
-      FieldInfo[] fieldInfos = typeof(TState).GetFields(
-        BindingFlags.Public | BindingFlags.NonPublic |
-        BindingFlags.Instance | BindingFlags.FlattenHierarchy
-      );
-      for(int index = 0; index < fieldInfos.Length; ++index) {
-        FieldInfo fieldInfo = fieldInfos[index];
-        if(fieldInfo.FieldType.IsPrimitive) {
-          object boxedValue = fieldInfo.GetValue(boxedOriginal);
-          fieldInfo.SetValue(boxedTarget, boxedValue);
-        } else if(fieldInfo.FieldType.IsValueType) {
-          object boxedOriginalValue = fieldInfo.GetValue(boxedOriginal);
-          Type originalType = boxedOriginalValue.GetType();
-          object boxedClonedValue = Activator.CreateInstance(originalType);
-          deepCopyReferenceTypeFieldBased(originalType, boxedOriginalValue, boxedClonedValue);
-          fieldInfo.SetValue(boxedTarget, boxedClonedValue);
+      int dimensionCount = original.Rank;
+
+      // Find out the length of each of the array's dimensions, also calculate how
+      // many elements there are in the array in total.
+      var lengths = new int[dimensionCount];
+      int totalElementCount = 0;
+      for(int index = 0; index < dimensionCount; ++index) {
+        lengths[index] = original.GetLength(index);
+        if(index == 0) {
+          totalElementCount = lengths[index];
         } else {
-          object originalValue = fieldInfo.GetValue(boxedOriginal);
-          if(originalValue != null) {
-            Type originalType = originalValue.GetType();
-            object clonedValue = Activator.CreateInstance(originalType);
-            deepCopyReferenceTypeFieldBased(originalType, originalValue, clonedValue);
-            fieldInfo.SetValue(boxedTarget, clonedValue);
-          }
+          totalElementCount *= lengths[index];
         }
       }
 
-      target = (TState)boxedTarget;
-    }
+      // Knowing the number of dimensions and the length of each dimension, we can
+      // create another array of the exact same sizes.
+      Array clone = Array.CreateInstance(elementType, lengths);
 
-    /// Creates a property-based shallow copy of a value type
-    /// Value type that will be copied
-    /// Original object that will be copied
-    /// Target object into which copied values will be written
-    private static void deepCopyValueTypePropertyBased(
-      ref TState original, ref TState target
-    ) {
-      object boxedOriginal = original;
-      object boxedTarget = Activator.CreateInstance(original.GetType());
+      // If this is a one-dimensional array (most common type), do an optimized copy
+      // directly specifying the indices
+      if(dimensionCount == 1) {
 
-      PropertyInfo[] propertyInfos = typeof(TState).GetProperties(
-        BindingFlags.Public | BindingFlags.NonPublic |
-        BindingFlags.Instance | BindingFlags.FlattenHierarchy
-      );
-      for(int index = 0; index < propertyInfos.Length; ++index) {
-        PropertyInfo propertyInfo = propertyInfos[index];
-        if(propertyInfo.CanRead && propertyInfo.CanWrite) {
-          if(propertyInfo.PropertyType.IsPrimitive) {
-            propertyInfo.SetValue(
-              boxedTarget,
-              propertyInfo.GetValue(boxedOriginal, null),
-              null
-            );
-          } else if(propertyInfo.PropertyType.IsValueType) {
-            object boxedOriginalValue = propertyInfo.GetValue(boxedOriginal, null);
-            Type originalType = boxedOriginalValue.GetType();
-            object boxedClonedValue = Activator.CreateInstance(originalType);
-            deepCopyReferenceTypePropertyBased(
-              originalType, boxedOriginalValue, boxedClonedValue
-            );
-            propertyInfo.SetValue(boxedTarget, boxedClonedValue, null);
-          } else {
-            object originalValue = propertyInfo.GetValue(boxedOriginal, null);
-            if(originalValue != null) {
-              Type originalType = originalValue.GetType();
-              object clonedValue = Activator.CreateInstance(originalType);
-              deepCopyReferenceTypePropertyBased(originalType, originalValue, clonedValue);
-              propertyInfo.SetValue(boxedTarget, clonedValue, null);
-            }
+        // Clone each element of the array directly
+        for(int index = 0; index < totalElementCount; ++index) {
+          object originalElement = original.GetValue(index);
+          if(originalElement != null) {
+            clone.SetValue(deepCloneSinglePropertyBased(originalElement), index);
           }
         }
+
+      } else { // Otherwise use the generic code for multi-dimensional arrays
+
+        var indices = new int[dimensionCount];
+        for(int index = 0; index < totalElementCount; ++index) {
+
+          // Determine the index for each of the array's dimensions
+          int elementIndex = index;
+          for(int dimensionIndex = dimensionCount - 1; dimensionIndex >= 0; --dimensionIndex) {
+            indices[dimensionIndex] = elementIndex % lengths[dimensionIndex];
+            elementIndex /= lengths[dimensionIndex];
+          }
+
+          // Clone the current array element
+          object originalElement = original.GetValue(indices);
+          if(originalElement != null) {
+            clone.SetValue(deepCloneSinglePropertyBased(originalElement), indices);
+          }
+
+        }
+
       }
 
-      target = (TState)boxedTarget;
+      return clone;
     }
 
   }