Streamlined the cloning API: whether a property-based clone is performed is no longer indicated through a parameter, but by calling the appropriate method
git-svn-id: file:///srv/devel/repo-conversion/nusu@245 d2e56fa2-650e-0410-a79f-9358c0239efd
This commit is contained in:
parent
0f2bb60ea5
commit
15300676ba
|
@ -40,7 +40,7 @@ namespace Nuclex.Support.Cloning {
|
||||||
[Test]
|
[Test]
|
||||||
public void PrimitiveTypesCanBeCloned() {
|
public void PrimitiveTypesCanBeCloned() {
|
||||||
int original = 12345;
|
int original = 12345;
|
||||||
int clone = this.cloneFactory.DeepClone(original, false);
|
int clone = this.cloneFactory.DeepFieldClone(original);
|
||||||
Assert.AreEqual(original, clone);
|
Assert.AreEqual(original, clone);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -48,7 +48,7 @@ namespace Nuclex.Support.Cloning {
|
||||||
[Test]
|
[Test]
|
||||||
public void ReferenceTypesCanBeCloned() {
|
public void ReferenceTypesCanBeCloned() {
|
||||||
var original = new TestReferenceType() { TestField = 123, TestProperty = 456 };
|
var original = new TestReferenceType() { TestField = 123, TestProperty = 456 };
|
||||||
TestReferenceType clone = this.cloneFactory.DeepClone(original, false);
|
TestReferenceType clone = this.cloneFactory.DeepFieldClone(original);
|
||||||
|
|
||||||
Assert.AreNotSame(original, clone);
|
Assert.AreNotSame(original, clone);
|
||||||
Assert.AreEqual(original.TestField, clone.TestField);
|
Assert.AreEqual(original.TestField, clone.TestField);
|
||||||
|
@ -59,7 +59,7 @@ namespace Nuclex.Support.Cloning {
|
||||||
[Test]
|
[Test]
|
||||||
public void PrimitiveArraysCanBeCloned() {
|
public void PrimitiveArraysCanBeCloned() {
|
||||||
var original = new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
|
var original = new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
|
||||||
int[] clone = this.cloneFactory.DeepClone(original, false);
|
int[] clone = this.cloneFactory.DeepFieldClone(original);
|
||||||
|
|
||||||
Assert.AreNotSame(original, clone);
|
Assert.AreNotSame(original, clone);
|
||||||
CollectionAssert.AreEqual(original, clone);
|
CollectionAssert.AreEqual(original, clone);
|
||||||
|
@ -71,7 +71,7 @@ namespace Nuclex.Support.Cloning {
|
||||||
var original = new TestReferenceType[] {
|
var original = new TestReferenceType[] {
|
||||||
new TestReferenceType() { TestField = 123, TestProperty = 456 }
|
new TestReferenceType() { TestField = 123, TestProperty = 456 }
|
||||||
};
|
};
|
||||||
TestReferenceType[] clone = this.cloneFactory.ShallowClone(original, false);
|
TestReferenceType[] clone = this.cloneFactory.ShallowFieldClone(original);
|
||||||
|
|
||||||
Assert.AreSame(original[0], clone[0]);
|
Assert.AreSame(original[0], clone[0]);
|
||||||
}
|
}
|
||||||
|
@ -84,7 +84,7 @@ namespace Nuclex.Support.Cloning {
|
||||||
new TestReferenceType() { TestField = 123, TestProperty = 456 }
|
new TestReferenceType() { TestField = 123, TestProperty = 456 }
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
TestReferenceType[,] clone = this.cloneFactory.DeepClone(original, false);
|
TestReferenceType[,] clone = this.cloneFactory.DeepFieldClone(original);
|
||||||
|
|
||||||
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);
|
||||||
|
@ -95,7 +95,7 @@ namespace Nuclex.Support.Cloning {
|
||||||
[Test]
|
[Test]
|
||||||
public void GenericListsCanBeCloned() {
|
public void GenericListsCanBeCloned() {
|
||||||
var original = new List<int>(new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 });
|
var original = new List<int>(new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 });
|
||||||
List<int> clone = this.cloneFactory.DeepClone(original, false);
|
List<int> clone = this.cloneFactory.DeepFieldClone(original);
|
||||||
|
|
||||||
CollectionAssert.AreEqual(original, clone);
|
CollectionAssert.AreEqual(original, clone);
|
||||||
}
|
}
|
||||||
|
@ -105,7 +105,7 @@ namespace Nuclex.Support.Cloning {
|
||||||
public void GenericDictionariesCanBeCloned() {
|
public void GenericDictionariesCanBeCloned() {
|
||||||
var original = new Dictionary<int, string>();
|
var original = new Dictionary<int, string>();
|
||||||
original.Add(1, "one");
|
original.Add(1, "one");
|
||||||
Dictionary<int, string> clone = this.cloneFactory.DeepClone(original, false);
|
Dictionary<int, string> clone = this.cloneFactory.DeepFieldClone(original);
|
||||||
|
|
||||||
Assert.AreEqual("one", clone[1]);
|
Assert.AreEqual("one", clone[1]);
|
||||||
}
|
}
|
||||||
|
@ -116,7 +116,7 @@ namespace Nuclex.Support.Cloning {
|
||||||
[Test]
|
[Test]
|
||||||
public void ShallowFieldBasedClonesOfValueTypesCanBeMade() {
|
public void ShallowFieldBasedClonesOfValueTypesCanBeMade() {
|
||||||
HierarchicalValueType original = CreateValueType();
|
HierarchicalValueType original = CreateValueType();
|
||||||
HierarchicalValueType clone = this.cloneFactory.ShallowClone(original, false);
|
HierarchicalValueType clone = this.cloneFactory.ShallowFieldClone(original);
|
||||||
VerifyClone(ref original, ref clone, isDeepClone: false, isPropertyBasedClone: false);
|
VerifyClone(ref original, ref clone, isDeepClone: false, isPropertyBasedClone: false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -126,7 +126,7 @@ namespace Nuclex.Support.Cloning {
|
||||||
[Test]
|
[Test]
|
||||||
public void ShallowFieldBasedClonesOfReferenceTypesCanBeMade() {
|
public void ShallowFieldBasedClonesOfReferenceTypesCanBeMade() {
|
||||||
HierarchicalReferenceType original = CreateReferenceType();
|
HierarchicalReferenceType original = CreateReferenceType();
|
||||||
HierarchicalReferenceType clone = this.cloneFactory.ShallowClone(original, false);
|
HierarchicalReferenceType clone = this.cloneFactory.ShallowFieldClone(original);
|
||||||
VerifyClone(original, clone, isDeepClone: false, isPropertyBasedClone: false);
|
VerifyClone(original, clone, isDeepClone: false, isPropertyBasedClone: false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -136,7 +136,7 @@ namespace Nuclex.Support.Cloning {
|
||||||
[Test]
|
[Test]
|
||||||
public void DeepFieldBasedClonesOfValueTypesCanBeMade() {
|
public void DeepFieldBasedClonesOfValueTypesCanBeMade() {
|
||||||
HierarchicalValueType original = CreateValueType();
|
HierarchicalValueType original = CreateValueType();
|
||||||
HierarchicalValueType clone = this.cloneFactory.DeepClone(original, false);
|
HierarchicalValueType clone = this.cloneFactory.DeepFieldClone(original);
|
||||||
VerifyClone(ref original, ref clone, isDeepClone: true, isPropertyBasedClone: false);
|
VerifyClone(ref original, ref clone, isDeepClone: true, isPropertyBasedClone: false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -146,7 +146,7 @@ namespace Nuclex.Support.Cloning {
|
||||||
[Test]
|
[Test]
|
||||||
public void DeepFieldBasedClonesOfReferenceTypesCanBeMade() {
|
public void DeepFieldBasedClonesOfReferenceTypesCanBeMade() {
|
||||||
HierarchicalReferenceType original = CreateReferenceType();
|
HierarchicalReferenceType original = CreateReferenceType();
|
||||||
HierarchicalReferenceType clone = this.cloneFactory.DeepClone(original, false);
|
HierarchicalReferenceType clone = this.cloneFactory.DeepFieldClone(original);
|
||||||
VerifyClone(original, clone, isDeepClone: true, isPropertyBasedClone: false);
|
VerifyClone(original, clone, isDeepClone: true, isPropertyBasedClone: false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -178,7 +178,7 @@ namespace Nuclex.Support.Cloning {
|
||||||
[Test]
|
[Test]
|
||||||
public void DeepPropertyBasedClonesOfValueTypesCanBeMade() {
|
public void DeepPropertyBasedClonesOfValueTypesCanBeMade() {
|
||||||
HierarchicalValueType original = CreateValueType();
|
HierarchicalValueType original = CreateValueType();
|
||||||
HierarchicalValueType clone = this.cloneFactory.DeepClone(original, true);
|
HierarchicalValueType clone = this.cloneFactory.DeepPropertyClone(original);
|
||||||
VerifyClone(ref original, ref clone, isDeepClone: true, isPropertyBasedClone: true);
|
VerifyClone(ref original, ref clone, isDeepClone: true, isPropertyBasedClone: true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -188,7 +188,7 @@ namespace Nuclex.Support.Cloning {
|
||||||
[Test]
|
[Test]
|
||||||
public void DeepPropertyBasedClonesOfReferenceTypesCanBeMade() {
|
public void DeepPropertyBasedClonesOfReferenceTypesCanBeMade() {
|
||||||
HierarchicalReferenceType original = CreateReferenceType();
|
HierarchicalReferenceType original = CreateReferenceType();
|
||||||
HierarchicalReferenceType clone = this.cloneFactory.DeepClone(original, true);
|
HierarchicalReferenceType clone = this.cloneFactory.DeepPropertyClone(original);
|
||||||
VerifyClone(original, clone, isDeepClone: true, isPropertyBasedClone: true);
|
VerifyClone(original, clone, isDeepClone: true, isPropertyBasedClone: true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -45,66 +45,32 @@ namespace Nuclex.Support.Cloning {
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <typeparam name="TCloned">Type of the object that will be cloned</typeparam>
|
/// <typeparam name="TCloned">Type of the object that will be cloned</typeparam>
|
||||||
/// <param name="objectToClone">Object that will be cloned</param>
|
/// <param name="objectToClone">Object that will be cloned</param>
|
||||||
/// <param name="usePropertyBasedClone">
|
|
||||||
/// Whether to clone the object based on its properties only
|
|
||||||
/// </param>
|
|
||||||
/// <returns>A deep clone of the provided object</returns>
|
/// <returns>A deep clone of the provided object</returns>
|
||||||
public static TCloned DeepClone<TCloned>(
|
public static TCloned DeepFieldClone<TCloned>(TCloned objectToClone) {
|
||||||
TCloned objectToClone, bool usePropertyBasedClone
|
|
||||||
) {
|
|
||||||
object objectToCloneAsObject = objectToClone;
|
object objectToCloneAsObject = objectToClone;
|
||||||
if(objectToCloneAsObject == null) {
|
if(objectToCloneAsObject == null) {
|
||||||
return default(TCloned);
|
return default(TCloned);
|
||||||
}
|
}
|
||||||
|
|
||||||
Func<object, object> cloner;
|
Func<object, object> cloner = getOrCreateDeepFieldBasedCloner(typeof(TCloned));
|
||||||
if(usePropertyBasedClone) {
|
|
||||||
cloner = getOrCreateDeepPropertyBasedCloner(typeof(TCloned));
|
|
||||||
} else {
|
|
||||||
cloner = getOrCreateDeepFieldBasedCloner(typeof(TCloned));
|
|
||||||
}
|
|
||||||
return (TCloned)cloner(objectToCloneAsObject);
|
return (TCloned)cloner(objectToCloneAsObject);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Creates a shallow clone of the specified object, reusing any referenced objects
|
|
||||||
/// </summary>
|
|
||||||
/// <typeparam name="TCloned">Type of the object that will be cloned</typeparam>
|
|
||||||
/// <param name="objectToClone">Object that will be cloned</param>
|
|
||||||
/// <param name="usePropertyBasedClone">
|
|
||||||
/// Whether to clone the object based on its properties only
|
|
||||||
/// </param>
|
|
||||||
/// <returns>A shallow clone of the provided object</returns>
|
|
||||||
public static TCloned ShallowClone<TCloned>(
|
|
||||||
TCloned objectToClone, bool usePropertyBasedClone
|
|
||||||
) {
|
|
||||||
object objectToCloneAsObject = objectToClone;
|
|
||||||
if(objectToCloneAsObject == null) {
|
|
||||||
return default(TCloned);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(usePropertyBasedClone) {
|
|
||||||
throw new NotImplementedException("Not implemented yet");
|
|
||||||
} else {
|
|
||||||
Func<object, object> cloner = getOrCreateShallowFieldBasedCloner(typeof(TCloned));
|
|
||||||
return (TCloned)cloner(objectToCloneAsObject);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Creates a deep clone of the specified object, also creating clones of all
|
/// Creates a deep clone of the specified object, also creating clones of all
|
||||||
/// child objects being referenced
|
/// child objects being referenced
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <typeparam name="TCloned">Type of the object that will be cloned</typeparam>
|
/// <typeparam name="TCloned">Type of the object that will be cloned</typeparam>
|
||||||
/// <param name="objectToClone">Object that will be cloned</param>
|
/// <param name="objectToClone">Object that will be cloned</param>
|
||||||
/// <param name="usePropertyBasedClone">
|
|
||||||
/// Whether to clone the object based on its properties only
|
|
||||||
/// </param>
|
|
||||||
/// <returns>A deep clone of the provided object</returns>
|
/// <returns>A deep clone of the provided object</returns>
|
||||||
TCloned ICloneFactory.DeepClone<TCloned>(
|
public static TCloned DeepPropertyClone<TCloned>(TCloned objectToClone) {
|
||||||
TCloned objectToClone, bool usePropertyBasedClone
|
object objectToCloneAsObject = objectToClone;
|
||||||
) {
|
if(objectToCloneAsObject == null) {
|
||||||
return ExpressionTreeCloner.DeepClone<TCloned>(objectToClone, usePropertyBasedClone);
|
return default(TCloned);
|
||||||
|
}
|
||||||
|
|
||||||
|
Func<object, object> cloner = getOrCreateDeepPropertyBasedCloner(typeof(TCloned));
|
||||||
|
return (TCloned)cloner(objectToCloneAsObject);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -112,14 +78,74 @@ namespace Nuclex.Support.Cloning {
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <typeparam name="TCloned">Type of the object that will be cloned</typeparam>
|
/// <typeparam name="TCloned">Type of the object that will be cloned</typeparam>
|
||||||
/// <param name="objectToClone">Object that will be cloned</param>
|
/// <param name="objectToClone">Object that will be cloned</param>
|
||||||
/// <param name="usePropertyBasedClone">
|
|
||||||
/// Whether to clone the object based on its properties only
|
|
||||||
/// </param>
|
|
||||||
/// <returns>A shallow clone of the provided object</returns>
|
/// <returns>A shallow clone of the provided object</returns>
|
||||||
TCloned ICloneFactory.ShallowClone<TCloned>(
|
public static TCloned ShallowFieldClone<TCloned>(TCloned objectToClone) {
|
||||||
TCloned objectToClone, bool usePropertyBasedClone
|
object objectToCloneAsObject = objectToClone;
|
||||||
) {
|
if(objectToCloneAsObject == null) {
|
||||||
return ExpressionTreeCloner.ShallowClone<TCloned>(objectToClone, usePropertyBasedClone);
|
return default(TCloned);
|
||||||
|
}
|
||||||
|
|
||||||
|
Func<object, object> cloner = getOrCreateShallowFieldBasedCloner(typeof(TCloned));
|
||||||
|
return (TCloned)cloner(objectToCloneAsObject);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a shallow clone of the specified object, reusing any referenced objects
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="TCloned">Type of the object that will be cloned</typeparam>
|
||||||
|
/// <param name="objectToClone">Object that will be cloned</param>
|
||||||
|
/// <returns>A shallow clone of the provided object</returns>
|
||||||
|
public static TCloned ShallowPropertyClone<TCloned>(TCloned objectToClone) {
|
||||||
|
object objectToCloneAsObject = objectToClone;
|
||||||
|
if(objectToCloneAsObject == null) {
|
||||||
|
return default(TCloned);
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new NotImplementedException("Not implemented yet");
|
||||||
|
Func<object, object> cloner = getOrCreateShallowFieldBasedCloner(typeof(TCloned));
|
||||||
|
return (TCloned)cloner(objectToCloneAsObject);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a shallow clone of the specified object, reusing any referenced objects
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="TCloned">Type of the object that will be cloned</typeparam>
|
||||||
|
/// <param name="objectToClone">Object that will be cloned</param>
|
||||||
|
/// <returns>A shallow clone of the provided object</returns>
|
||||||
|
TCloned ICloneFactory.ShallowFieldClone<TCloned>(TCloned objectToClone) {
|
||||||
|
return ExpressionTreeCloner.ShallowFieldClone<TCloned>(objectToClone);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a shallow clone of the specified object, reusing any referenced objects
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="TCloned">Type of the object that will be cloned</typeparam>
|
||||||
|
/// <param name="objectToClone">Object that will be cloned</param>
|
||||||
|
/// <returns>A shallow clone of the provided object</returns>
|
||||||
|
TCloned ICloneFactory.ShallowPropertyClone<TCloned>(TCloned objectToClone) {
|
||||||
|
return ExpressionTreeCloner.ShallowPropertyClone<TCloned>(objectToClone);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a deep clone of the specified object, also creating clones of all
|
||||||
|
/// child objects being referenced
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="TCloned">Type of the object that will be cloned</typeparam>
|
||||||
|
/// <param name="objectToClone">Object that will be cloned</param>
|
||||||
|
/// <returns>A deep clone of the provided object</returns>
|
||||||
|
TCloned ICloneFactory.DeepFieldClone<TCloned>(TCloned objectToClone) {
|
||||||
|
return ExpressionTreeCloner.DeepFieldClone<TCloned>(objectToClone);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a deep clone of the specified object, also creating clones of all
|
||||||
|
/// child objects being referenced
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="TCloned">Type of the object that will be cloned</typeparam>
|
||||||
|
/// <param name="objectToClone">Object that will be cloned</param>
|
||||||
|
/// <returns>A deep clone of the provided object</returns>
|
||||||
|
TCloned ICloneFactory.DeepPropertyClone<TCloned>(TCloned objectToClone) {
|
||||||
|
return ExpressionTreeCloner.DeepPropertyClone<TCloned>(objectToClone);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if false
|
#if false
|
||||||
|
|
|
@ -26,39 +26,74 @@ namespace Nuclex.Support.Cloning {
|
||||||
public interface ICloneFactory {
|
public interface ICloneFactory {
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Creates a deep clone of the specified object, also creating clones of all
|
/// Creates a shallow clone of the specified object, reusing any referenced objects
|
||||||
/// child objects being referenced
|
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <typeparam name="TCloned">Type of the object that will be cloned</typeparam>
|
/// <typeparam name="TCloned">Type of the object that will be cloned</typeparam>
|
||||||
/// <param name="objectToClone">Object that will be cloned</param>
|
/// <param name="objectToClone">Object that will be cloned</param>
|
||||||
/// <param name="usePropertyBasedClone">
|
/// <returns>A shallow clone of the provided object</returns>
|
||||||
/// Whether to clone the object based on its properties only
|
|
||||||
/// </param>
|
|
||||||
/// <returns>A deep clone of the provided object</returns>
|
|
||||||
/// <remarks>
|
/// <remarks>
|
||||||
/// A property-based clone is useful if you're using dynamically generated proxies,
|
/// Field-based clones are guaranteed to be complete - there will be no missed
|
||||||
/// such as when working with entities returned by an ORM like NHibernate.
|
/// members. This type of clone is also able to clone types that do not provide
|
||||||
/// When not using a property-based clone, internal proxy fields would be cloned
|
/// a default constructor.
|
||||||
/// and might cause problems with the ORM.
|
|
||||||
/// </remarks>
|
/// </remarks>
|
||||||
TCloned DeepClone<TCloned>(TCloned objectToClone, bool usePropertyBasedClone);
|
TCloned ShallowFieldClone<TCloned>(TCloned objectToClone);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Creates a shallow clone of the specified object, reusing any referenced objects
|
/// Creates a shallow clone of the specified object, reusing any referenced objects
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <typeparam name="TCloned">Type of the object that will be cloned</typeparam>
|
/// <typeparam name="TCloned">Type of the object that will be cloned</typeparam>
|
||||||
/// <param name="objectToClone">Object that will be cloned</param>
|
/// <param name="objectToClone">Object that will be cloned</param>
|
||||||
/// <param name="usePropertyBasedClone">
|
|
||||||
/// Whether to clone the object based on its properties only
|
|
||||||
/// </param>
|
|
||||||
/// <returns>A shallow clone of the provided object</returns>
|
/// <returns>A shallow clone of the provided object</returns>
|
||||||
/// <remarks>
|
/// <remarks>
|
||||||
|
/// <para>
|
||||||
/// A property-based clone is useful if you're using dynamically generated proxies,
|
/// A property-based clone is useful if you're using dynamically generated proxies,
|
||||||
/// such as when working with entities returned by an ORM like NHibernate.
|
/// such as when working with entities returned by an ORM like NHibernate.
|
||||||
/// When not using a property-based clone, internal proxy fields would be cloned
|
/// When not using a property-based clone, internal proxy fields would be cloned
|
||||||
/// and might cause problems with the ORM.
|
/// and might cause problems with the ORM.
|
||||||
|
/// </para>
|
||||||
|
/// <para>
|
||||||
|
/// Property-based clones require a default constructor because there's no guarantee
|
||||||
|
/// that all fields will are assignable through properties and starting with
|
||||||
|
/// an uninitialized object is likely to end up with a broken clone.
|
||||||
|
/// </para>
|
||||||
/// </remarks>
|
/// </remarks>
|
||||||
TCloned ShallowClone<TCloned>(TCloned objectToClone, bool usePropertyBasedClone);
|
TCloned ShallowPropertyClone<TCloned>(TCloned objectToClone);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a deep clone of the specified object, also creating clones of all
|
||||||
|
/// child objects being referenced
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="TCloned">Type of the object that will be cloned</typeparam>
|
||||||
|
/// <param name="objectToClone">Object that will be cloned</param>
|
||||||
|
/// <returns>A deep clone of the provided object</returns>
|
||||||
|
/// <remarks>
|
||||||
|
/// Field-based clones are guaranteed to be complete - there will be no missed
|
||||||
|
/// members. This type of clone is also able to clone types that do not provide
|
||||||
|
/// a default constructor.
|
||||||
|
/// </remarks>
|
||||||
|
TCloned DeepFieldClone<TCloned>(TCloned objectToClone);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a deep clone of the specified object, also creating clones of all
|
||||||
|
/// child objects being referenced
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="TCloned">Type of the object that will be cloned</typeparam>
|
||||||
|
/// <param name="objectToClone">Object that will be cloned</param>
|
||||||
|
/// <returns>A deep clone of the provided object</returns>
|
||||||
|
/// <remarks>
|
||||||
|
/// <para>
|
||||||
|
/// A property-based clone is useful if you're using dynamically generated proxies,
|
||||||
|
/// such as when working with entities returned by an ORM like NHibernate.
|
||||||
|
/// When not using a property-based clone, internal proxy fields would be cloned
|
||||||
|
/// and might cause problems with the ORM.
|
||||||
|
/// </para>
|
||||||
|
/// <para>
|
||||||
|
/// Property-based clones require a default constructor because there's no guarantee
|
||||||
|
/// that all fields will are assignable through properties and starting with
|
||||||
|
/// an uninitialized object is likely to end up with a broken clone.
|
||||||
|
/// </para>
|
||||||
|
/// </remarks>
|
||||||
|
TCloned DeepPropertyClone<TCloned>(TCloned objectToClone);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -40,7 +40,7 @@ namespace Nuclex.Support.Cloning {
|
||||||
[Test]
|
[Test]
|
||||||
public void PrimitiveTypesCanBeCloned() {
|
public void PrimitiveTypesCanBeCloned() {
|
||||||
int original = 12345;
|
int original = 12345;
|
||||||
int clone = this.cloneFactory.ShallowClone(original, false);
|
int clone = this.cloneFactory.ShallowFieldClone(original);
|
||||||
Assert.AreEqual(original, clone);
|
Assert.AreEqual(original, clone);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -50,7 +50,7 @@ namespace Nuclex.Support.Cloning {
|
||||||
var original = new TestReferenceType[] {
|
var original = new TestReferenceType[] {
|
||||||
new TestReferenceType() { TestField = 123, TestProperty = 456 }
|
new TestReferenceType() { TestField = 123, TestProperty = 456 }
|
||||||
};
|
};
|
||||||
TestReferenceType[] clone = this.cloneFactory.ShallowClone(original, false);
|
TestReferenceType[] clone = this.cloneFactory.ShallowFieldClone(original);
|
||||||
|
|
||||||
Assert.AreSame(original[0], clone[0]);
|
Assert.AreSame(original[0], clone[0]);
|
||||||
}
|
}
|
||||||
|
@ -61,7 +61,7 @@ namespace Nuclex.Support.Cloning {
|
||||||
var original = new TestReferenceType[] {
|
var original = new TestReferenceType[] {
|
||||||
new TestReferenceType() { TestField = 123, TestProperty = 456 }
|
new TestReferenceType() { TestField = 123, TestProperty = 456 }
|
||||||
};
|
};
|
||||||
TestReferenceType[] clone = this.cloneFactory.DeepClone(original, false);
|
TestReferenceType[] clone = this.cloneFactory.DeepFieldClone(original);
|
||||||
|
|
||||||
Assert.AreNotSame(original[0], clone[0]);
|
Assert.AreNotSame(original[0], clone[0]);
|
||||||
Assert.AreEqual(original[0].TestField, clone[0].TestField);
|
Assert.AreEqual(original[0].TestField, clone[0].TestField);
|
||||||
|
@ -72,7 +72,7 @@ namespace Nuclex.Support.Cloning {
|
||||||
[Test]
|
[Test]
|
||||||
public void GenericListsCanBeCloned() {
|
public void GenericListsCanBeCloned() {
|
||||||
var original = new List<int>(new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 });
|
var original = new List<int>(new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 });
|
||||||
List<int> clone = this.cloneFactory.DeepClone(original, false);
|
List<int> clone = this.cloneFactory.DeepFieldClone(original);
|
||||||
|
|
||||||
CollectionAssert.AreEqual(original, clone);
|
CollectionAssert.AreEqual(original, clone);
|
||||||
}
|
}
|
||||||
|
@ -82,7 +82,7 @@ namespace Nuclex.Support.Cloning {
|
||||||
public void GenericDictionariesCanBeCloned() {
|
public void GenericDictionariesCanBeCloned() {
|
||||||
var original = new Dictionary<int, string>();
|
var original = new Dictionary<int, string>();
|
||||||
original.Add(1, "one");
|
original.Add(1, "one");
|
||||||
Dictionary<int, string> clone = this.cloneFactory.DeepClone(original, false);
|
Dictionary<int, string> clone = this.cloneFactory.DeepFieldClone(original);
|
||||||
|
|
||||||
Assert.AreEqual("one", clone[1]);
|
Assert.AreEqual("one", clone[1]);
|
||||||
}
|
}
|
||||||
|
@ -93,7 +93,7 @@ namespace Nuclex.Support.Cloning {
|
||||||
[Test]
|
[Test]
|
||||||
public void ShallowFieldBasedClonesOfValueTypesCanBeMade() {
|
public void ShallowFieldBasedClonesOfValueTypesCanBeMade() {
|
||||||
HierarchicalValueType original = CreateValueType();
|
HierarchicalValueType original = CreateValueType();
|
||||||
HierarchicalValueType clone = this.cloneFactory.ShallowClone(original, false);
|
HierarchicalValueType clone = this.cloneFactory.ShallowFieldClone(original);
|
||||||
VerifyClone(ref original, ref clone, isDeepClone: false, isPropertyBasedClone: false);
|
VerifyClone(ref original, ref clone, isDeepClone: false, isPropertyBasedClone: false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -103,7 +103,7 @@ namespace Nuclex.Support.Cloning {
|
||||||
[Test]
|
[Test]
|
||||||
public void ShallowFieldBasedClonesOfReferenceTypesCanBeMade() {
|
public void ShallowFieldBasedClonesOfReferenceTypesCanBeMade() {
|
||||||
HierarchicalReferenceType original = CreateReferenceType();
|
HierarchicalReferenceType original = CreateReferenceType();
|
||||||
HierarchicalReferenceType clone = this.cloneFactory.ShallowClone(original, false);
|
HierarchicalReferenceType clone = this.cloneFactory.ShallowFieldClone(original);
|
||||||
VerifyClone(original, clone, isDeepClone: false, isPropertyBasedClone: false);
|
VerifyClone(original, clone, isDeepClone: false, isPropertyBasedClone: false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -113,7 +113,7 @@ namespace Nuclex.Support.Cloning {
|
||||||
[Test]
|
[Test]
|
||||||
public void DeepFieldBasedClonesOfValueTypesCanBeMade() {
|
public void DeepFieldBasedClonesOfValueTypesCanBeMade() {
|
||||||
HierarchicalValueType original = CreateValueType();
|
HierarchicalValueType original = CreateValueType();
|
||||||
HierarchicalValueType clone = this.cloneFactory.DeepClone(original, false);
|
HierarchicalValueType clone = this.cloneFactory.DeepFieldClone(original);
|
||||||
VerifyClone(ref original, ref clone, isDeepClone: true, isPropertyBasedClone: false);
|
VerifyClone(ref original, ref clone, isDeepClone: true, isPropertyBasedClone: false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -123,7 +123,7 @@ namespace Nuclex.Support.Cloning {
|
||||||
[Test]
|
[Test]
|
||||||
public void DeepFieldBasedClonesOfReferenceTypesCanBeMade() {
|
public void DeepFieldBasedClonesOfReferenceTypesCanBeMade() {
|
||||||
HierarchicalReferenceType original = CreateReferenceType();
|
HierarchicalReferenceType original = CreateReferenceType();
|
||||||
HierarchicalReferenceType clone = this.cloneFactory.DeepClone(original, false);
|
HierarchicalReferenceType clone = this.cloneFactory.DeepFieldClone(original);
|
||||||
VerifyClone(original, clone, isDeepClone: true, isPropertyBasedClone: false);
|
VerifyClone(original, clone, isDeepClone: true, isPropertyBasedClone: false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -133,7 +133,7 @@ namespace Nuclex.Support.Cloning {
|
||||||
[Test]
|
[Test]
|
||||||
public void ShallowPropertyBasedClonesOfValueTypesCanBeMade() {
|
public void ShallowPropertyBasedClonesOfValueTypesCanBeMade() {
|
||||||
HierarchicalValueType original = CreateValueType();
|
HierarchicalValueType original = CreateValueType();
|
||||||
HierarchicalValueType clone = this.cloneFactory.ShallowClone(original, true);
|
HierarchicalValueType clone = this.cloneFactory.ShallowPropertyClone(original);
|
||||||
VerifyClone(ref original, ref clone, isDeepClone: false, isPropertyBasedClone: true);
|
VerifyClone(ref original, ref clone, isDeepClone: false, isPropertyBasedClone: true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -143,7 +143,7 @@ namespace Nuclex.Support.Cloning {
|
||||||
[Test]
|
[Test]
|
||||||
public void ShallowPropertyBasedClonesOfReferenceTypesCanBeMade() {
|
public void ShallowPropertyBasedClonesOfReferenceTypesCanBeMade() {
|
||||||
HierarchicalReferenceType original = CreateReferenceType();
|
HierarchicalReferenceType original = CreateReferenceType();
|
||||||
HierarchicalReferenceType clone = this.cloneFactory.ShallowClone(original, true);
|
HierarchicalReferenceType clone = this.cloneFactory.ShallowPropertyClone(original);
|
||||||
VerifyClone(original, clone, isDeepClone: false, isPropertyBasedClone: true);
|
VerifyClone(original, clone, isDeepClone: false, isPropertyBasedClone: true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -153,7 +153,7 @@ namespace Nuclex.Support.Cloning {
|
||||||
[Test]
|
[Test]
|
||||||
public void DeepPropertyBasedClonesOfValueTypesCanBeMade() {
|
public void DeepPropertyBasedClonesOfValueTypesCanBeMade() {
|
||||||
HierarchicalValueType original = CreateValueType();
|
HierarchicalValueType original = CreateValueType();
|
||||||
HierarchicalValueType clone = this.cloneFactory.DeepClone(original, true);
|
HierarchicalValueType clone = this.cloneFactory.DeepPropertyClone(original);
|
||||||
VerifyClone(ref original, ref clone, isDeepClone: true, isPropertyBasedClone: true);
|
VerifyClone(ref original, ref clone, isDeepClone: true, isPropertyBasedClone: true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -163,7 +163,7 @@ namespace Nuclex.Support.Cloning {
|
||||||
[Test]
|
[Test]
|
||||||
public void DeepPropertyBasedClonesOfReferenceTypesCanBeMade() {
|
public void DeepPropertyBasedClonesOfReferenceTypesCanBeMade() {
|
||||||
HierarchicalReferenceType original = CreateReferenceType();
|
HierarchicalReferenceType original = CreateReferenceType();
|
||||||
HierarchicalReferenceType clone = this.cloneFactory.DeepClone(original, true);
|
HierarchicalReferenceType clone = this.cloneFactory.DeepPropertyClone(original);
|
||||||
VerifyClone(original, clone, isDeepClone: true, isPropertyBasedClone: true);
|
VerifyClone(original, clone, isDeepClone: true, isPropertyBasedClone: true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -39,52 +39,19 @@ namespace Nuclex.Support.Cloning {
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <typeparam name="TCloned">Type of the object that will be cloned</typeparam>
|
/// <typeparam name="TCloned">Type of the object that will be cloned</typeparam>
|
||||||
/// <param name="objectToClone">Object that will be cloned</param>
|
/// <param name="objectToClone">Object that will be cloned</param>
|
||||||
/// <param name="usePropertyBasedClone">
|
|
||||||
/// Whether to clone the object based on its properties only
|
|
||||||
/// </param>
|
|
||||||
/// <returns>A shallow clone of the provided object</returns>
|
/// <returns>A shallow clone of the provided object</returns>
|
||||||
public static TCloned ShallowClone<TCloned>(
|
public static TCloned ShallowFieldClone<TCloned>(TCloned objectToClone) {
|
||||||
TCloned objectToClone, bool usePropertyBasedClone
|
|
||||||
) {
|
|
||||||
Type originalType = objectToClone.GetType();
|
Type originalType = objectToClone.GetType();
|
||||||
if(originalType.IsPrimitive || (originalType == typeof(string))) {
|
if(originalType.IsPrimitive || (originalType == typeof(string))) {
|
||||||
return objectToClone; // Being value types, primitives are copied by default
|
return objectToClone; // Being value types, primitives are copied by default
|
||||||
} else if(originalType.IsArray) {
|
} else if(originalType.IsArray) {
|
||||||
return (TCloned)shallowCloneArray(objectToClone);
|
return (TCloned)shallowCloneArray(objectToClone);
|
||||||
} else if(originalType.IsValueType) {
|
} else if(originalType.IsValueType) {
|
||||||
if(usePropertyBasedClone) {
|
|
||||||
return (TCloned)shallowCloneComplexPropertyBased(objectToClone);
|
|
||||||
} else {
|
|
||||||
return objectToClone; // Value types can be copied directly
|
return objectToClone; // Value types can be copied directly
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if(usePropertyBasedClone) {
|
|
||||||
return (TCloned)shallowCloneComplexPropertyBased(objectToClone);
|
|
||||||
} else {
|
} else {
|
||||||
return (TCloned)shallowCloneComplexFieldBased(objectToClone);
|
return (TCloned)shallowCloneComplexFieldBased(objectToClone);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Creates a deep clone of the specified object, also creating clones of all
|
|
||||||
/// child objects being referenced
|
|
||||||
/// </summary>
|
|
||||||
/// <typeparam name="TCloned">Type of the object that will be cloned</typeparam>
|
|
||||||
/// <param name="objectToClone">Object that will be cloned</param>
|
|
||||||
/// <param name="usePropertyBasedClone">
|
|
||||||
/// Whether to clone the object based on its properties only
|
|
||||||
/// </param>
|
|
||||||
/// <returns>A deep clone of the provided object</returns>
|
|
||||||
public static TCloned DeepClone<TCloned>(
|
|
||||||
TCloned objectToClone, bool usePropertyBasedClone
|
|
||||||
) {
|
|
||||||
if(usePropertyBasedClone) {
|
|
||||||
return (TCloned)deepCloneSinglePropertyBased(objectToClone);
|
|
||||||
} else {
|
|
||||||
return (TCloned)deepCloneSingleFieldBased(objectToClone);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Creates a shallow clone of the specified object, reusing any referenced objects
|
/// Creates a shallow clone of the specified object, reusing any referenced objects
|
||||||
|
@ -95,10 +62,17 @@ namespace Nuclex.Support.Cloning {
|
||||||
/// Whether to clone the object based on its properties only
|
/// Whether to clone the object based on its properties only
|
||||||
/// </param>
|
/// </param>
|
||||||
/// <returns>A shallow clone of the provided object</returns>
|
/// <returns>A shallow clone of the provided object</returns>
|
||||||
TCloned ICloneFactory.ShallowClone<TCloned>(
|
public static TCloned ShallowPropertyClone<TCloned>(TCloned objectToClone) {
|
||||||
TCloned objectToClone, bool usePropertyBasedClone
|
Type originalType = objectToClone.GetType();
|
||||||
) {
|
if(originalType.IsPrimitive || (originalType == typeof(string))) {
|
||||||
return ReflectionCloner.ShallowClone<TCloned>(objectToClone, usePropertyBasedClone);
|
return objectToClone; // Being value types, primitives are copied by default
|
||||||
|
} else if(originalType.IsArray) {
|
||||||
|
return (TCloned)shallowCloneArray(objectToClone);
|
||||||
|
} else if(originalType.IsValueType) {
|
||||||
|
return (TCloned)shallowCloneComplexPropertyBased(objectToClone);
|
||||||
|
} else {
|
||||||
|
return (TCloned)shallowCloneComplexPropertyBased(objectToClone);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -107,12 +81,62 @@ namespace Nuclex.Support.Cloning {
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <typeparam name="TCloned">Type of the object that will be cloned</typeparam>
|
/// <typeparam name="TCloned">Type of the object that will be cloned</typeparam>
|
||||||
/// <param name="objectToClone">Object that will be cloned</param>
|
/// <param name="objectToClone">Object that will be cloned</param>
|
||||||
/// <param name="usePropertyBasedClone">
|
|
||||||
/// Whether to clone the object based on its properties only
|
|
||||||
/// </param>
|
|
||||||
/// <returns>A deep clone of the provided object</returns>
|
/// <returns>A deep clone of the provided object</returns>
|
||||||
TCloned ICloneFactory.DeepClone<TCloned>(TCloned objectToClone, bool usePropertyBasedClone) {
|
public static TCloned DeepFieldClone<TCloned>(TCloned objectToClone) {
|
||||||
return ReflectionCloner.DeepClone<TCloned>(objectToClone, usePropertyBasedClone);
|
return (TCloned)deepCloneSingleFieldBased(objectToClone);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a deep clone of the specified object, also creating clones of all
|
||||||
|
/// child objects being referenced
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="TCloned">Type of the object that will be cloned</typeparam>
|
||||||
|
/// <param name="objectToClone">Object that will be cloned</param>
|
||||||
|
/// <returns>A deep clone of the provided object</returns>
|
||||||
|
public static TCloned DeepPropertyClone<TCloned>(TCloned objectToClone) {
|
||||||
|
return (TCloned)deepCloneSinglePropertyBased(objectToClone);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a shallow clone of the specified object, reusing any referenced objects
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="TCloned">Type of the object that will be cloned</typeparam>
|
||||||
|
/// <param name="objectToClone">Object that will be cloned</param>
|
||||||
|
/// <returns>A shallow clone of the provided object</returns>
|
||||||
|
TCloned ICloneFactory.ShallowFieldClone<TCloned>(TCloned objectToClone) {
|
||||||
|
return ReflectionCloner.ShallowFieldClone<TCloned>(objectToClone);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a shallow clone of the specified object, reusing any referenced objects
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="TCloned">Type of the object that will be cloned</typeparam>
|
||||||
|
/// <param name="objectToClone">Object that will be cloned</param>
|
||||||
|
/// <returns>A shallow clone of the provided object</returns>
|
||||||
|
TCloned ICloneFactory.ShallowPropertyClone<TCloned>(TCloned objectToClone) {
|
||||||
|
return ReflectionCloner.ShallowPropertyClone<TCloned>(objectToClone);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a deep clone of the specified object, also creating clones of all
|
||||||
|
/// child objects being referenced
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="TCloned">Type of the object that will be cloned</typeparam>
|
||||||
|
/// <param name="objectToClone">Object that will be cloned</param>
|
||||||
|
/// <returns>A deep clone of the provided object</returns>
|
||||||
|
TCloned ICloneFactory.DeepFieldClone<TCloned>(TCloned objectToClone) {
|
||||||
|
return ReflectionCloner.DeepFieldClone<TCloned>(objectToClone);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a deep clone of the specified object, also creating clones of all
|
||||||
|
/// child objects being referenced
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="TCloned">Type of the object that will be cloned</typeparam>
|
||||||
|
/// <param name="objectToClone">Object that will be cloned</param>
|
||||||
|
/// <returns>A deep clone of the provided object</returns>
|
||||||
|
TCloned ICloneFactory.DeepPropertyClone<TCloned>(TCloned objectToClone) {
|
||||||
|
return ReflectionCloner.DeepPropertyClone<TCloned>(objectToClone);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>Clones a complex type using field-based value transfer</summary>
|
/// <summary>Clones a complex type using field-based value transfer</summary>
|
||||||
|
|
|
@ -40,7 +40,7 @@ namespace Nuclex.Support.Cloning {
|
||||||
[Test]
|
[Test]
|
||||||
public void PrimitiveTypesCanBeCloned() {
|
public void PrimitiveTypesCanBeCloned() {
|
||||||
int original = 12345;
|
int original = 12345;
|
||||||
int clone = this.cloneFactory.DeepClone(original, false);
|
int clone = this.cloneFactory.DeepFieldClone(original);
|
||||||
Assert.AreEqual(original, clone);
|
Assert.AreEqual(original, clone);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -50,7 +50,7 @@ namespace Nuclex.Support.Cloning {
|
||||||
var original = new TestReferenceType[] {
|
var original = new TestReferenceType[] {
|
||||||
new TestReferenceType() { TestField = 123, TestProperty = 456 }
|
new TestReferenceType() { TestField = 123, TestProperty = 456 }
|
||||||
};
|
};
|
||||||
TestReferenceType[] clone = this.cloneFactory.DeepClone(original, false);
|
TestReferenceType[] clone = this.cloneFactory.DeepFieldClone(original);
|
||||||
|
|
||||||
Assert.AreNotSame(original[0], clone[0]);
|
Assert.AreNotSame(original[0], clone[0]);
|
||||||
Assert.AreEqual(original[0].TestField, clone[0].TestField);
|
Assert.AreEqual(original[0].TestField, clone[0].TestField);
|
||||||
|
@ -61,7 +61,7 @@ namespace Nuclex.Support.Cloning {
|
||||||
[Test]
|
[Test]
|
||||||
public void GenericListsCanBeCloned() {
|
public void GenericListsCanBeCloned() {
|
||||||
var original = new List<int>(new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 });
|
var original = new List<int>(new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 });
|
||||||
List<int> clone = this.cloneFactory.DeepClone(original, false);
|
List<int> clone = this.cloneFactory.DeepFieldClone(original);
|
||||||
|
|
||||||
CollectionAssert.AreEqual(original, clone);
|
CollectionAssert.AreEqual(original, clone);
|
||||||
}
|
}
|
||||||
|
@ -71,7 +71,7 @@ namespace Nuclex.Support.Cloning {
|
||||||
public void GenericDictionariesCanBeCloned() {
|
public void GenericDictionariesCanBeCloned() {
|
||||||
var original = new Dictionary<int, string>();
|
var original = new Dictionary<int, string>();
|
||||||
original.Add(1, "one");
|
original.Add(1, "one");
|
||||||
Dictionary<int, string> clone = this.cloneFactory.DeepClone(original, false);
|
Dictionary<int, string> clone = this.cloneFactory.DeepFieldClone(original);
|
||||||
|
|
||||||
Assert.AreEqual("one", clone[1]);
|
Assert.AreEqual("one", clone[1]);
|
||||||
}
|
}
|
||||||
|
@ -82,7 +82,7 @@ namespace Nuclex.Support.Cloning {
|
||||||
[Test]
|
[Test]
|
||||||
public void DeepFieldBasedClonesOfValueTypesCanBeMade() {
|
public void DeepFieldBasedClonesOfValueTypesCanBeMade() {
|
||||||
HierarchicalValueType original = CreateValueType();
|
HierarchicalValueType original = CreateValueType();
|
||||||
HierarchicalValueType clone = this.cloneFactory.DeepClone(original, false);
|
HierarchicalValueType clone = this.cloneFactory.DeepFieldClone(original);
|
||||||
VerifyClone(ref original, ref clone, isDeepClone: true, isPropertyBasedClone: false);
|
VerifyClone(ref original, ref clone, isDeepClone: true, isPropertyBasedClone: false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -92,7 +92,7 @@ namespace Nuclex.Support.Cloning {
|
||||||
[Test]
|
[Test]
|
||||||
public void DeepFieldBasedClonesOfReferenceTypesCanBeMade() {
|
public void DeepFieldBasedClonesOfReferenceTypesCanBeMade() {
|
||||||
HierarchicalReferenceType original = CreateReferenceType();
|
HierarchicalReferenceType original = CreateReferenceType();
|
||||||
HierarchicalReferenceType clone = this.cloneFactory.DeepClone(original, false);
|
HierarchicalReferenceType clone = this.cloneFactory.DeepFieldClone(original);
|
||||||
VerifyClone(original, clone, isDeepClone: true, isPropertyBasedClone: false);
|
VerifyClone(original, clone, isDeepClone: true, isPropertyBasedClone: false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -102,7 +102,7 @@ namespace Nuclex.Support.Cloning {
|
||||||
[Test]
|
[Test]
|
||||||
public void DeepPropertyBasedClonesOfValueTypesCanBeMade() {
|
public void DeepPropertyBasedClonesOfValueTypesCanBeMade() {
|
||||||
HierarchicalValueType original = CreateValueType();
|
HierarchicalValueType original = CreateValueType();
|
||||||
HierarchicalValueType clone = this.cloneFactory.DeepClone(original, true);
|
HierarchicalValueType clone = this.cloneFactory.DeepPropertyClone(original);
|
||||||
VerifyClone(ref original, ref clone, isDeepClone: true, isPropertyBasedClone: true);
|
VerifyClone(ref original, ref clone, isDeepClone: true, isPropertyBasedClone: true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -112,7 +112,7 @@ namespace Nuclex.Support.Cloning {
|
||||||
[Test]
|
[Test]
|
||||||
public void DeepPropertyBasedClonesOfReferenceTypesCanBeMade() {
|
public void DeepPropertyBasedClonesOfReferenceTypesCanBeMade() {
|
||||||
HierarchicalReferenceType original = CreateReferenceType();
|
HierarchicalReferenceType original = CreateReferenceType();
|
||||||
HierarchicalReferenceType clone = this.cloneFactory.DeepClone(original, true);
|
HierarchicalReferenceType clone = this.cloneFactory.DeepPropertyClone(original);
|
||||||
VerifyClone(original, clone, isDeepClone: true, isPropertyBasedClone: true);
|
VerifyClone(original, clone, isDeepClone: true, isPropertyBasedClone: true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -242,25 +242,14 @@ namespace Nuclex.Support.Cloning {
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <typeparam name="TCloned">Type of the object that will be cloned</typeparam>
|
/// <typeparam name="TCloned">Type of the object that will be cloned</typeparam>
|
||||||
/// <param name="objectToClone">Object that will be cloned</param>
|
/// <param name="objectToClone">Object that will be cloned</param>
|
||||||
/// <param name="usePropertyBasedClone">
|
|
||||||
/// Whether to clone the object based on its properties only
|
|
||||||
/// </param>
|
|
||||||
/// <returns>A deep clone of the provided object</returns>
|
/// <returns>A deep clone of the provided object</returns>
|
||||||
public static TCloned DeepClone<TCloned>(
|
public static TCloned DeepFieldClone<TCloned>(TCloned objectToClone) {
|
||||||
TCloned objectToClone, bool usePropertyBasedClone
|
|
||||||
) {
|
|
||||||
using(var memoryStream = new MemoryStream()) {
|
using(var memoryStream = new MemoryStream()) {
|
||||||
if(usePropertyBasedClone) {
|
|
||||||
propertyBasedFormatter.Serialize(memoryStream, objectToClone);
|
|
||||||
memoryStream.Position = 0;
|
|
||||||
return (TCloned)propertyBasedFormatter.Deserialize(memoryStream);
|
|
||||||
} else {
|
|
||||||
fieldBasedFormatter.Serialize(memoryStream, objectToClone);
|
fieldBasedFormatter.Serialize(memoryStream, objectToClone);
|
||||||
memoryStream.Position = 0;
|
memoryStream.Position = 0;
|
||||||
return (TCloned)fieldBasedFormatter.Deserialize(memoryStream);
|
return (TCloned)fieldBasedFormatter.Deserialize(memoryStream);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Creates a deep clone of the specified object, also creating clones of all
|
/// Creates a deep clone of the specified object, also creating clones of all
|
||||||
|
@ -268,14 +257,13 @@ namespace Nuclex.Support.Cloning {
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <typeparam name="TCloned">Type of the object that will be cloned</typeparam>
|
/// <typeparam name="TCloned">Type of the object that will be cloned</typeparam>
|
||||||
/// <param name="objectToClone">Object that will be cloned</param>
|
/// <param name="objectToClone">Object that will be cloned</param>
|
||||||
/// <param name="usePropertyBasedClone">
|
|
||||||
/// Whether to clone the object based on its properties only
|
|
||||||
/// </param>
|
|
||||||
/// <returns>A deep clone of the provided object</returns>
|
/// <returns>A deep clone of the provided object</returns>
|
||||||
TCloned ICloneFactory.DeepClone<TCloned>(
|
public static TCloned DeepPropertyClone<TCloned>(TCloned objectToClone) {
|
||||||
TCloned objectToClone, bool usePropertyBasedClone
|
using(var memoryStream = new MemoryStream()) {
|
||||||
) {
|
propertyBasedFormatter.Serialize(memoryStream, objectToClone);
|
||||||
return SerializationCloner.DeepClone<TCloned>(objectToClone, usePropertyBasedClone);
|
memoryStream.Position = 0;
|
||||||
|
return (TCloned)propertyBasedFormatter.Deserialize(memoryStream);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -283,16 +271,43 @@ namespace Nuclex.Support.Cloning {
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <typeparam name="TCloned">Type of the object that will be cloned</typeparam>
|
/// <typeparam name="TCloned">Type of the object that will be cloned</typeparam>
|
||||||
/// <param name="objectToClone">Object that will be cloned</param>
|
/// <param name="objectToClone">Object that will be cloned</param>
|
||||||
/// <param name="usePropertyBasedClone">
|
|
||||||
/// Whether to clone the object based on its properties only
|
|
||||||
/// </param>
|
|
||||||
/// <returns>A shallow clone of the provided object</returns>
|
/// <returns>A shallow clone of the provided object</returns>
|
||||||
TCloned ICloneFactory.ShallowClone<TCloned>(
|
TCloned ICloneFactory.ShallowFieldClone<TCloned>(TCloned objectToClone) {
|
||||||
TCloned objectToClone, bool usePropertyBasedClone
|
|
||||||
) {
|
|
||||||
throw new NotSupportedException("The serialization cloner cannot create shallow clones");
|
throw new NotSupportedException("The serialization cloner cannot create shallow clones");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a shallow clone of the specified object, reusing any referenced objects
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="TCloned">Type of the object that will be cloned</typeparam>
|
||||||
|
/// <param name="objectToClone">Object that will be cloned</param>
|
||||||
|
/// <returns>A shallow clone of the provided object</returns>
|
||||||
|
TCloned ICloneFactory.ShallowPropertyClone<TCloned>(TCloned objectToClone) {
|
||||||
|
throw new NotSupportedException("The serialization cloner cannot create shallow clones");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a deep clone of the specified object, also creating clones of all
|
||||||
|
/// child objects being referenced
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="TCloned">Type of the object that will be cloned</typeparam>
|
||||||
|
/// <param name="objectToClone">Object that will be cloned</param>
|
||||||
|
/// <returns>A deep clone of the provided object</returns>
|
||||||
|
TCloned ICloneFactory.DeepFieldClone<TCloned>(TCloned objectToClone) {
|
||||||
|
return SerializationCloner.DeepFieldClone<TCloned>(objectToClone);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a deep clone of the specified object, also creating clones of all
|
||||||
|
/// child objects being referenced
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="TCloned">Type of the object that will be cloned</typeparam>
|
||||||
|
/// <param name="objectToClone">Object that will be cloned</param>
|
||||||
|
/// <returns>A deep clone of the provided object</returns>
|
||||||
|
TCloned ICloneFactory.DeepPropertyClone<TCloned>(TCloned objectToClone) {
|
||||||
|
return SerializationCloner.DeepPropertyClone<TCloned>(objectToClone);
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>Serializes objects by storing their fields</summary>
|
/// <summary>Serializes objects by storing their fields</summary>
|
||||||
private static BinaryFormatter fieldBasedFormatter;
|
private static BinaryFormatter fieldBasedFormatter;
|
||||||
/// <summary>Serializes objects by storing their properties</summary>
|
/// <summary>Serializes objects by storing their properties</summary>
|
||||||
|
|
Loading…
Reference in New Issue
Block a user