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]
|
||||
public void PrimitiveTypesCanBeCloned() {
|
||||
int original = 12345;
|
||||
int clone = this.cloneFactory.DeepClone(original, false);
|
||||
int clone = this.cloneFactory.DeepFieldClone(original);
|
||||
Assert.AreEqual(original, clone);
|
||||
}
|
||||
|
||||
|
@ -48,7 +48,7 @@ namespace Nuclex.Support.Cloning {
|
|||
[Test]
|
||||
public void ReferenceTypesCanBeCloned() {
|
||||
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.AreEqual(original.TestField, clone.TestField);
|
||||
|
@ -59,7 +59,7 @@ namespace Nuclex.Support.Cloning {
|
|||
[Test]
|
||||
public void PrimitiveArraysCanBeCloned() {
|
||||
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);
|
||||
CollectionAssert.AreEqual(original, clone);
|
||||
|
@ -71,7 +71,7 @@ namespace Nuclex.Support.Cloning {
|
|||
var original = new TestReferenceType[] {
|
||||
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]);
|
||||
}
|
||||
|
@ -84,7 +84,7 @@ namespace Nuclex.Support.Cloning {
|
|||
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.AreEqual(original[0, 0].TestField, clone[0, 0].TestField);
|
||||
|
@ -95,7 +95,7 @@ namespace Nuclex.Support.Cloning {
|
|||
[Test]
|
||||
public void GenericListsCanBeCloned() {
|
||||
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);
|
||||
}
|
||||
|
@ -105,7 +105,7 @@ namespace Nuclex.Support.Cloning {
|
|||
public void GenericDictionariesCanBeCloned() {
|
||||
var original = new Dictionary<int, string>();
|
||||
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]);
|
||||
}
|
||||
|
@ -116,7 +116,7 @@ namespace Nuclex.Support.Cloning {
|
|||
[Test]
|
||||
public void ShallowFieldBasedClonesOfValueTypesCanBeMade() {
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -126,7 +126,7 @@ namespace Nuclex.Support.Cloning {
|
|||
[Test]
|
||||
public void ShallowFieldBasedClonesOfReferenceTypesCanBeMade() {
|
||||
HierarchicalReferenceType original = CreateReferenceType();
|
||||
HierarchicalReferenceType clone = this.cloneFactory.ShallowClone(original, false);
|
||||
HierarchicalReferenceType clone = this.cloneFactory.ShallowFieldClone(original);
|
||||
VerifyClone(original, clone, isDeepClone: false, isPropertyBasedClone: false);
|
||||
}
|
||||
|
||||
|
@ -136,7 +136,7 @@ namespace Nuclex.Support.Cloning {
|
|||
[Test]
|
||||
public void DeepFieldBasedClonesOfValueTypesCanBeMade() {
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -146,7 +146,7 @@ namespace Nuclex.Support.Cloning {
|
|||
[Test]
|
||||
public void DeepFieldBasedClonesOfReferenceTypesCanBeMade() {
|
||||
HierarchicalReferenceType original = CreateReferenceType();
|
||||
HierarchicalReferenceType clone = this.cloneFactory.DeepClone(original, false);
|
||||
HierarchicalReferenceType clone = this.cloneFactory.DeepFieldClone(original);
|
||||
VerifyClone(original, clone, isDeepClone: true, isPropertyBasedClone: false);
|
||||
}
|
||||
|
||||
|
@ -178,7 +178,7 @@ namespace Nuclex.Support.Cloning {
|
|||
[Test]
|
||||
public void DeepPropertyBasedClonesOfValueTypesCanBeMade() {
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -188,7 +188,7 @@ namespace Nuclex.Support.Cloning {
|
|||
[Test]
|
||||
public void DeepPropertyBasedClonesOfReferenceTypesCanBeMade() {
|
||||
HierarchicalReferenceType original = CreateReferenceType();
|
||||
HierarchicalReferenceType clone = this.cloneFactory.DeepClone(original, true);
|
||||
HierarchicalReferenceType clone = this.cloneFactory.DeepPropertyClone(original);
|
||||
VerifyClone(original, clone, isDeepClone: true, isPropertyBasedClone: true);
|
||||
}
|
||||
|
||||
|
|
|
@ -45,66 +45,32 @@ namespace Nuclex.Support.Cloning {
|
|||
/// </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
|
||||
) {
|
||||
public static TCloned DeepFieldClone<TCloned>(TCloned objectToClone) {
|
||||
object objectToCloneAsObject = objectToClone;
|
||||
if(objectToCloneAsObject == null) {
|
||||
return default(TCloned);
|
||||
}
|
||||
|
||||
Func<object, object> cloner;
|
||||
if(usePropertyBasedClone) {
|
||||
cloner = getOrCreateDeepPropertyBasedCloner(typeof(TCloned));
|
||||
} else {
|
||||
cloner = getOrCreateDeepFieldBasedCloner(typeof(TCloned));
|
||||
}
|
||||
Func<object, object> cloner = getOrCreateDeepFieldBasedCloner(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>
|
||||
/// <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>
|
||||
/// 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>
|
||||
TCloned ICloneFactory.DeepClone<TCloned>(
|
||||
TCloned objectToClone, bool usePropertyBasedClone
|
||||
) {
|
||||
return ExpressionTreeCloner.DeepClone<TCloned>(objectToClone, usePropertyBasedClone);
|
||||
public static TCloned DeepPropertyClone<TCloned>(TCloned objectToClone) {
|
||||
object objectToCloneAsObject = objectToClone;
|
||||
if(objectToCloneAsObject == null) {
|
||||
return default(TCloned);
|
||||
}
|
||||
|
||||
Func<object, object> cloner = getOrCreateDeepPropertyBasedCloner(typeof(TCloned));
|
||||
return (TCloned)cloner(objectToCloneAsObject);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -112,14 +78,74 @@ namespace Nuclex.Support.Cloning {
|
|||
/// </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>
|
||||
TCloned ICloneFactory.ShallowClone<TCloned>(
|
||||
TCloned objectToClone, bool usePropertyBasedClone
|
||||
) {
|
||||
return ExpressionTreeCloner.ShallowClone<TCloned>(objectToClone, usePropertyBasedClone);
|
||||
public static TCloned ShallowFieldClone<TCloned>(TCloned objectToClone) {
|
||||
object objectToCloneAsObject = objectToClone;
|
||||
if(objectToCloneAsObject == null) {
|
||||
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
|
||||
|
|
|
@ -26,39 +26,74 @@ namespace Nuclex.Support.Cloning {
|
|||
public interface ICloneFactory {
|
||||
|
||||
/// <summary>
|
||||
/// Creates a deep clone of the specified object, also creating clones of all
|
||||
/// child objects being referenced
|
||||
/// 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 deep clone of the provided object</returns>
|
||||
/// <returns>A shallow clone of the provided object</returns>
|
||||
/// <remarks>
|
||||
/// 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.
|
||||
/// 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 DeepClone<TCloned>(TCloned objectToClone, bool usePropertyBasedClone);
|
||||
TCloned ShallowFieldClone<TCloned>(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>
|
||||
/// <param name="usePropertyBasedClone">
|
||||
/// Whether to clone the object based on its properties only
|
||||
/// </param>
|
||||
/// <returns>A shallow clone of the provided object</returns>
|
||||
/// <remarks>
|
||||
/// 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>
|
||||
/// 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 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]
|
||||
public void PrimitiveTypesCanBeCloned() {
|
||||
int original = 12345;
|
||||
int clone = this.cloneFactory.ShallowClone(original, false);
|
||||
int clone = this.cloneFactory.ShallowFieldClone(original);
|
||||
Assert.AreEqual(original, clone);
|
||||
}
|
||||
|
||||
|
@ -50,7 +50,7 @@ namespace Nuclex.Support.Cloning {
|
|||
var original = new TestReferenceType[] {
|
||||
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]);
|
||||
}
|
||||
|
@ -61,7 +61,7 @@ namespace Nuclex.Support.Cloning {
|
|||
var original = new TestReferenceType[] {
|
||||
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.AreEqual(original[0].TestField, clone[0].TestField);
|
||||
|
@ -72,7 +72,7 @@ namespace Nuclex.Support.Cloning {
|
|||
[Test]
|
||||
public void GenericListsCanBeCloned() {
|
||||
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);
|
||||
}
|
||||
|
@ -82,7 +82,7 @@ namespace Nuclex.Support.Cloning {
|
|||
public void GenericDictionariesCanBeCloned() {
|
||||
var original = new Dictionary<int, string>();
|
||||
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]);
|
||||
}
|
||||
|
@ -93,7 +93,7 @@ namespace Nuclex.Support.Cloning {
|
|||
[Test]
|
||||
public void ShallowFieldBasedClonesOfValueTypesCanBeMade() {
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -103,7 +103,7 @@ namespace Nuclex.Support.Cloning {
|
|||
[Test]
|
||||
public void ShallowFieldBasedClonesOfReferenceTypesCanBeMade() {
|
||||
HierarchicalReferenceType original = CreateReferenceType();
|
||||
HierarchicalReferenceType clone = this.cloneFactory.ShallowClone(original, false);
|
||||
HierarchicalReferenceType clone = this.cloneFactory.ShallowFieldClone(original);
|
||||
VerifyClone(original, clone, isDeepClone: false, isPropertyBasedClone: false);
|
||||
}
|
||||
|
||||
|
@ -113,7 +113,7 @@ namespace Nuclex.Support.Cloning {
|
|||
[Test]
|
||||
public void DeepFieldBasedClonesOfValueTypesCanBeMade() {
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -123,7 +123,7 @@ namespace Nuclex.Support.Cloning {
|
|||
[Test]
|
||||
public void DeepFieldBasedClonesOfReferenceTypesCanBeMade() {
|
||||
HierarchicalReferenceType original = CreateReferenceType();
|
||||
HierarchicalReferenceType clone = this.cloneFactory.DeepClone(original, false);
|
||||
HierarchicalReferenceType clone = this.cloneFactory.DeepFieldClone(original);
|
||||
VerifyClone(original, clone, isDeepClone: true, isPropertyBasedClone: false);
|
||||
}
|
||||
|
||||
|
@ -133,7 +133,7 @@ namespace Nuclex.Support.Cloning {
|
|||
[Test]
|
||||
public void ShallowPropertyBasedClonesOfValueTypesCanBeMade() {
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -143,7 +143,7 @@ namespace Nuclex.Support.Cloning {
|
|||
[Test]
|
||||
public void ShallowPropertyBasedClonesOfReferenceTypesCanBeMade() {
|
||||
HierarchicalReferenceType original = CreateReferenceType();
|
||||
HierarchicalReferenceType clone = this.cloneFactory.ShallowClone(original, true);
|
||||
HierarchicalReferenceType clone = this.cloneFactory.ShallowPropertyClone(original);
|
||||
VerifyClone(original, clone, isDeepClone: false, isPropertyBasedClone: true);
|
||||
}
|
||||
|
||||
|
@ -153,7 +153,7 @@ namespace Nuclex.Support.Cloning {
|
|||
[Test]
|
||||
public void DeepPropertyBasedClonesOfValueTypesCanBeMade() {
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -163,7 +163,7 @@ namespace Nuclex.Support.Cloning {
|
|||
[Test]
|
||||
public void DeepPropertyBasedClonesOfReferenceTypesCanBeMade() {
|
||||
HierarchicalReferenceType original = CreateReferenceType();
|
||||
HierarchicalReferenceType clone = this.cloneFactory.DeepClone(original, true);
|
||||
HierarchicalReferenceType clone = this.cloneFactory.DeepPropertyClone(original);
|
||||
VerifyClone(original, clone, isDeepClone: true, isPropertyBasedClone: true);
|
||||
}
|
||||
|
||||
|
|
|
@ -39,50 +39,17 @@ namespace Nuclex.Support.Cloning {
|
|||
/// </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
|
||||
) {
|
||||
public static TCloned ShallowFieldClone<TCloned>(TCloned objectToClone) {
|
||||
Type originalType = objectToClone.GetType();
|
||||
if(originalType.IsPrimitive || (originalType == typeof(string))) {
|
||||
return objectToClone; // Being value types, primitives are copied by default
|
||||
} else if(originalType.IsArray) {
|
||||
return (TCloned)shallowCloneArray(objectToClone);
|
||||
} 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 {
|
||||
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);
|
||||
return (TCloned)shallowCloneComplexFieldBased(objectToClone);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -95,10 +62,17 @@ namespace Nuclex.Support.Cloning {
|
|||
/// Whether to clone the object based on its properties only
|
||||
/// </param>
|
||||
/// <returns>A shallow clone of the provided object</returns>
|
||||
TCloned ICloneFactory.ShallowClone<TCloned>(
|
||||
TCloned objectToClone, bool usePropertyBasedClone
|
||||
) {
|
||||
return ReflectionCloner.ShallowClone<TCloned>(objectToClone, usePropertyBasedClone);
|
||||
public static TCloned ShallowPropertyClone<TCloned>(TCloned objectToClone) {
|
||||
Type originalType = objectToClone.GetType();
|
||||
if(originalType.IsPrimitive || (originalType == typeof(string))) {
|
||||
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>
|
||||
|
@ -107,12 +81,62 @@ namespace Nuclex.Support.Cloning {
|
|||
/// </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>
|
||||
TCloned ICloneFactory.DeepClone<TCloned>(TCloned objectToClone, bool usePropertyBasedClone) {
|
||||
return ReflectionCloner.DeepClone<TCloned>(objectToClone, usePropertyBasedClone);
|
||||
public static TCloned DeepFieldClone<TCloned>(TCloned objectToClone) {
|
||||
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>
|
||||
|
|
|
@ -40,7 +40,7 @@ namespace Nuclex.Support.Cloning {
|
|||
[Test]
|
||||
public void PrimitiveTypesCanBeCloned() {
|
||||
int original = 12345;
|
||||
int clone = this.cloneFactory.DeepClone(original, false);
|
||||
int clone = this.cloneFactory.DeepFieldClone(original);
|
||||
Assert.AreEqual(original, clone);
|
||||
}
|
||||
|
||||
|
@ -50,7 +50,7 @@ namespace Nuclex.Support.Cloning {
|
|||
var original = new TestReferenceType[] {
|
||||
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.AreEqual(original[0].TestField, clone[0].TestField);
|
||||
|
@ -61,7 +61,7 @@ namespace Nuclex.Support.Cloning {
|
|||
[Test]
|
||||
public void GenericListsCanBeCloned() {
|
||||
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);
|
||||
}
|
||||
|
@ -71,7 +71,7 @@ namespace Nuclex.Support.Cloning {
|
|||
public void GenericDictionariesCanBeCloned() {
|
||||
var original = new Dictionary<int, string>();
|
||||
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]);
|
||||
}
|
||||
|
@ -82,7 +82,7 @@ namespace Nuclex.Support.Cloning {
|
|||
[Test]
|
||||
public void DeepFieldBasedClonesOfValueTypesCanBeMade() {
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -92,7 +92,7 @@ namespace Nuclex.Support.Cloning {
|
|||
[Test]
|
||||
public void DeepFieldBasedClonesOfReferenceTypesCanBeMade() {
|
||||
HierarchicalReferenceType original = CreateReferenceType();
|
||||
HierarchicalReferenceType clone = this.cloneFactory.DeepClone(original, false);
|
||||
HierarchicalReferenceType clone = this.cloneFactory.DeepFieldClone(original);
|
||||
VerifyClone(original, clone, isDeepClone: true, isPropertyBasedClone: false);
|
||||
}
|
||||
|
||||
|
@ -102,7 +102,7 @@ namespace Nuclex.Support.Cloning {
|
|||
[Test]
|
||||
public void DeepPropertyBasedClonesOfValueTypesCanBeMade() {
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -112,7 +112,7 @@ namespace Nuclex.Support.Cloning {
|
|||
[Test]
|
||||
public void DeepPropertyBasedClonesOfReferenceTypesCanBeMade() {
|
||||
HierarchicalReferenceType original = CreateReferenceType();
|
||||
HierarchicalReferenceType clone = this.cloneFactory.DeepClone(original, true);
|
||||
HierarchicalReferenceType clone = this.cloneFactory.DeepPropertyClone(original);
|
||||
VerifyClone(original, clone, isDeepClone: true, isPropertyBasedClone: true);
|
||||
}
|
||||
|
||||
|
|
|
@ -242,23 +242,12 @@ namespace Nuclex.Support.Cloning {
|
|||
/// </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
|
||||
) {
|
||||
public static TCloned DeepFieldClone<TCloned>(TCloned objectToClone) {
|
||||
using(var memoryStream = new MemoryStream()) {
|
||||
if(usePropertyBasedClone) {
|
||||
propertyBasedFormatter.Serialize(memoryStream, objectToClone);
|
||||
memoryStream.Position = 0;
|
||||
return (TCloned)propertyBasedFormatter.Deserialize(memoryStream);
|
||||
} else {
|
||||
fieldBasedFormatter.Serialize(memoryStream, objectToClone);
|
||||
memoryStream.Position = 0;
|
||||
return (TCloned)fieldBasedFormatter.Deserialize(memoryStream);
|
||||
}
|
||||
fieldBasedFormatter.Serialize(memoryStream, objectToClone);
|
||||
memoryStream.Position = 0;
|
||||
return (TCloned)fieldBasedFormatter.Deserialize(memoryStream);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -268,14 +257,13 @@ namespace Nuclex.Support.Cloning {
|
|||
/// </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>
|
||||
TCloned ICloneFactory.DeepClone<TCloned>(
|
||||
TCloned objectToClone, bool usePropertyBasedClone
|
||||
) {
|
||||
return SerializationCloner.DeepClone<TCloned>(objectToClone, usePropertyBasedClone);
|
||||
public static TCloned DeepPropertyClone<TCloned>(TCloned objectToClone) {
|
||||
using(var memoryStream = new MemoryStream()) {
|
||||
propertyBasedFormatter.Serialize(memoryStream, objectToClone);
|
||||
memoryStream.Position = 0;
|
||||
return (TCloned)propertyBasedFormatter.Deserialize(memoryStream);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -283,16 +271,43 @@ namespace Nuclex.Support.Cloning {
|
|||
/// </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>
|
||||
TCloned ICloneFactory.ShallowClone<TCloned>(
|
||||
TCloned objectToClone, bool usePropertyBasedClone
|
||||
) {
|
||||
TCloned ICloneFactory.ShallowFieldClone<TCloned>(TCloned objectToClone) {
|
||||
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>
|
||||
private static BinaryFormatter fieldBasedFormatter;
|
||||
/// <summary>Serializes objects by storing their properties</summary>
|
||||
|
|
Loading…
Reference in New Issue
Block a user