There was still an issue with the cloners: private fields in base classes were not cloned properly - problem fixed and unit tests added to prevent regressions
git-svn-id: file:///srv/devel/repo-conversion/nusu@249 d2e56fa2-650e-0410-a79f-9358c0239efd
This commit is contained in:
		
							parent
							
								
									0290444140
								
							
						
					
					
						commit
						0fdad7c33d
					
				
					 10 changed files with 291 additions and 37 deletions
				
			
		|  | @ -61,6 +61,10 @@ | ||||||
|       <DependentUpon>AffineThreadPool.cs</DependentUpon> |       <DependentUpon>AffineThreadPool.cs</DependentUpon> | ||||||
|     </Compile> |     </Compile> | ||||||
|     <Compile Include="Source\Cloning\CloneFactoryTest.cs" /> |     <Compile Include="Source\Cloning\CloneFactoryTest.cs" /> | ||||||
|  |     <Compile Include="Source\Cloning\ClonerHelpers.cs" /> | ||||||
|  |     <Compile Include="Source\Cloning\ClonerHelpers.Test.cs"> | ||||||
|  |       <DependentUpon>ClonerHelpers.cs</DependentUpon> | ||||||
|  |     </Compile> | ||||||
|     <Compile Include="Source\Cloning\ExpressionTreeCloner.cs" /> |     <Compile Include="Source\Cloning\ExpressionTreeCloner.cs" /> | ||||||
|     <Compile Include="Source\Cloning\ExpressionTreeCloner.FieldBased.cs"> |     <Compile Include="Source\Cloning\ExpressionTreeCloner.FieldBased.cs"> | ||||||
|       <DependentUpon>ExpressionTreeCloner.cs</DependentUpon> |       <DependentUpon>ExpressionTreeCloner.cs</DependentUpon> | ||||||
|  |  | ||||||
|  | @ -92,6 +92,10 @@ | ||||||
|       <DependentUpon>AffineThreadPool.cs</DependentUpon> |       <DependentUpon>AffineThreadPool.cs</DependentUpon> | ||||||
|     </Compile> |     </Compile> | ||||||
|     <Compile Include="Source\Cloning\CloneFactoryTest.cs" /> |     <Compile Include="Source\Cloning\CloneFactoryTest.cs" /> | ||||||
|  |     <Compile Include="Source\Cloning\ClonerHelpers.cs" /> | ||||||
|  |     <Compile Include="Source\Cloning\ClonerHelpers.Test.cs"> | ||||||
|  |       <DependentUpon>ClonerHelpers.cs</DependentUpon> | ||||||
|  |     </Compile> | ||||||
|     <Compile Include="Source\Cloning\ExpressionTreeCloner.cs" /> |     <Compile Include="Source\Cloning\ExpressionTreeCloner.cs" /> | ||||||
|     <Compile Include="Source\Cloning\ExpressionTreeCloner.FieldBased.cs"> |     <Compile Include="Source\Cloning\ExpressionTreeCloner.FieldBased.cs"> | ||||||
|       <DependentUpon>ExpressionTreeCloner.cs</DependentUpon> |       <DependentUpon>ExpressionTreeCloner.cs</DependentUpon> | ||||||
|  |  | ||||||
|  | @ -103,6 +103,10 @@ | ||||||
|       <DependentUpon>AffineThreadPool.cs</DependentUpon> |       <DependentUpon>AffineThreadPool.cs</DependentUpon> | ||||||
|     </Compile> |     </Compile> | ||||||
|     <Compile Include="Source\Cloning\CloneFactoryTest.cs" /> |     <Compile Include="Source\Cloning\CloneFactoryTest.cs" /> | ||||||
|  |     <Compile Include="Source\Cloning\ClonerHelpers.cs" /> | ||||||
|  |     <Compile Include="Source\Cloning\ClonerHelpers.Test.cs"> | ||||||
|  |       <DependentUpon>ClonerHelpers.cs</DependentUpon> | ||||||
|  |     </Compile> | ||||||
|     <Compile Include="Source\Cloning\ExpressionTreeCloner.cs" /> |     <Compile Include="Source\Cloning\ExpressionTreeCloner.cs" /> | ||||||
|     <Compile Include="Source\Cloning\ExpressionTreeCloner.FieldBased.cs"> |     <Compile Include="Source\Cloning\ExpressionTreeCloner.FieldBased.cs"> | ||||||
|       <DependentUpon>ExpressionTreeCloner.cs</DependentUpon> |       <DependentUpon>ExpressionTreeCloner.cs</DependentUpon> | ||||||
|  |  | ||||||
|  | @ -27,7 +27,21 @@ using NUnit.Framework; | ||||||
| namespace Nuclex.Support.Cloning { | namespace Nuclex.Support.Cloning { | ||||||
| 
 | 
 | ||||||
|   /// <summary>Base class for unit tests verifying the clone factory</summary> |   /// <summary>Base class for unit tests verifying the clone factory</summary> | ||||||
|   internal abstract class CloneFactoryTest { |   public abstract class CloneFactoryTest { | ||||||
|  | 
 | ||||||
|  |     #region class DerivedReferenceType | ||||||
|  | 
 | ||||||
|  |     /// <summary>A derived reference type being used for testing</summary> | ||||||
|  |     protected class DerivedReferenceType : TestReferenceType { | ||||||
|  | 
 | ||||||
|  |       /// <summary>Field holding an integer value for testing</summary> | ||||||
|  |       public int DerivedField; | ||||||
|  |       /// <summary>Property holding an integer value for testing</summary> | ||||||
|  |       public int DerivedProperty { get; set; } | ||||||
|  | 
 | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     #endregion // class DerivedReferenceType | ||||||
| 
 | 
 | ||||||
|     #region class TestReferenceType |     #region class TestReferenceType | ||||||
| 
 | 
 | ||||||
|  | @ -84,8 +98,12 @@ namespace Nuclex.Support.Cloning { | ||||||
|       public TestReferenceType AlwaysNullProperty { get; set; } |       public TestReferenceType AlwaysNullProperty { get; set; } | ||||||
|       /// <summary>A property that only has a getter</summary> |       /// <summary>A property that only has a getter</summary> | ||||||
|       public TestReferenceType GetOnlyProperty { get { return null; } } |       public TestReferenceType GetOnlyProperty { get { return null; } } | ||||||
|       /// <summary>A property that only has a s</summary> |       /// <summary>A property that only has a setter</summary> | ||||||
|       public TestReferenceType SetOnlyProperty { set { } } |       public TestReferenceType SetOnlyProperty { set { } } | ||||||
|  |       /// <summary>Field typed as base class holding a derived instance</summary> | ||||||
|  |       public TestReferenceType DerivedField; | ||||||
|  |       /// <summary>Field typed as base class holding a derived instance</summary> | ||||||
|  |       public TestReferenceType DerivedProperty { get; set; } | ||||||
| 
 | 
 | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  | @ -120,6 +138,10 @@ namespace Nuclex.Support.Cloning { | ||||||
|       public TestReferenceType GetOnlyProperty { get { return null; } } |       public TestReferenceType GetOnlyProperty { get { return null; } } | ||||||
|       /// <summary>A property that only has a s</summary> |       /// <summary>A property that only has a s</summary> | ||||||
|       public TestReferenceType SetOnlyProperty { set { } } |       public TestReferenceType SetOnlyProperty { set { } } | ||||||
|  |       /// <summary>Field typed as base class holding a derived instance</summary> | ||||||
|  |       public TestReferenceType DerivedField; | ||||||
|  |       /// <summary>Field typed as base class holding a derived instance</summary> | ||||||
|  |       public TestReferenceType DerivedProperty { get; set; } | ||||||
| 
 | 
 | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  | @ -172,12 +194,21 @@ namespace Nuclex.Support.Cloning { | ||||||
|         Assert.AreEqual(0, clone.ValueTypeField.TestProperty); |         Assert.AreEqual(0, clone.ValueTypeField.TestProperty); | ||||||
|         Assert.AreEqual(0, clone.ValueTypeProperty.TestField); |         Assert.AreEqual(0, clone.ValueTypeProperty.TestField); | ||||||
|         Assert.IsNull(clone.ReferenceTypeField); |         Assert.IsNull(clone.ReferenceTypeField); | ||||||
|  |         Assert.IsNull(clone.DerivedField); | ||||||
| 
 | 
 | ||||||
|         if(isDeepClone) { |         if(isDeepClone) { | ||||||
|           Assert.AreNotSame(original.ReferenceTypeProperty, clone.ReferenceTypeProperty); |           Assert.AreNotSame(original.ReferenceTypeProperty, clone.ReferenceTypeProperty); | ||||||
|           Assert.AreNotSame( |           Assert.AreNotSame( | ||||||
|             original.ReferenceTypeArrayProperty, clone.ReferenceTypeArrayProperty |             original.ReferenceTypeArrayProperty, clone.ReferenceTypeArrayProperty | ||||||
|           ); |           ); | ||||||
|  |           Assert.AreNotSame(original.DerivedProperty, clone.DerivedProperty); | ||||||
|  |           Assert.IsInstanceOf<DerivedReferenceType>(clone.DerivedProperty); | ||||||
|  | 
 | ||||||
|  |           var originalDerived = (DerivedReferenceType)original.DerivedProperty; | ||||||
|  |           var clonedDerived = (DerivedReferenceType)clone.DerivedProperty; | ||||||
|  |           Assert.AreEqual(originalDerived.TestProperty, clonedDerived.TestProperty); | ||||||
|  |           Assert.AreEqual(originalDerived.DerivedProperty, clonedDerived.DerivedProperty); | ||||||
|  | 
 | ||||||
|           Assert.AreEqual(0, clone.ReferenceTypeProperty.TestField); |           Assert.AreEqual(0, clone.ReferenceTypeProperty.TestField); | ||||||
|           Assert.AreNotSame( |           Assert.AreNotSame( | ||||||
|             original.ReferenceTypeArrayProperty[1, 3][0], |             original.ReferenceTypeArrayProperty[1, 3][0], | ||||||
|  | @ -190,6 +221,7 @@ namespace Nuclex.Support.Cloning { | ||||||
|           Assert.AreEqual(0, clone.ReferenceTypeArrayProperty[1, 3][0].TestField); |           Assert.AreEqual(0, clone.ReferenceTypeArrayProperty[1, 3][0].TestField); | ||||||
|           Assert.AreEqual(0, clone.ReferenceTypeArrayProperty[1, 3][2].TestField); |           Assert.AreEqual(0, clone.ReferenceTypeArrayProperty[1, 3][2].TestField); | ||||||
|         } else { |         } else { | ||||||
|  |           Assert.AreSame(original.ReferenceTypeProperty, clone.ReferenceTypeProperty); | ||||||
|           Assert.AreSame(original.ReferenceTypeProperty, clone.ReferenceTypeProperty); |           Assert.AreSame(original.ReferenceTypeProperty, clone.ReferenceTypeProperty); | ||||||
|           Assert.AreSame( |           Assert.AreSame( | ||||||
|             original.ReferenceTypeArrayProperty, clone.ReferenceTypeArrayProperty |             original.ReferenceTypeArrayProperty, clone.ReferenceTypeArrayProperty | ||||||
|  | @ -215,6 +247,25 @@ namespace Nuclex.Support.Cloning { | ||||||
|         if(isDeepClone) { |         if(isDeepClone) { | ||||||
|           Assert.AreNotSame(original.ReferenceTypeField, clone.ReferenceTypeField); |           Assert.AreNotSame(original.ReferenceTypeField, clone.ReferenceTypeField); | ||||||
|           Assert.AreNotSame(original.ReferenceTypeProperty, clone.ReferenceTypeProperty); |           Assert.AreNotSame(original.ReferenceTypeProperty, clone.ReferenceTypeProperty); | ||||||
|  |           Assert.AreNotSame(original.DerivedField, clone.DerivedField); | ||||||
|  |           Assert.AreNotSame(original.DerivedProperty, clone.DerivedProperty); | ||||||
|  |           Assert.IsInstanceOf<DerivedReferenceType>(clone.DerivedField); | ||||||
|  |           Assert.IsInstanceOf<DerivedReferenceType>(clone.DerivedProperty); | ||||||
|  | 
 | ||||||
|  |           var originalDerived = (DerivedReferenceType)original.DerivedField; | ||||||
|  |           var clonedDerived = (DerivedReferenceType)clone.DerivedField; | ||||||
|  |           Assert.AreEqual(originalDerived.TestField, clonedDerived.TestField); | ||||||
|  |           Assert.AreEqual(originalDerived.TestProperty, clonedDerived.TestProperty); | ||||||
|  |           Assert.AreEqual(originalDerived.DerivedField, clonedDerived.DerivedField); | ||||||
|  |           Assert.AreEqual(originalDerived.DerivedProperty, clonedDerived.DerivedProperty); | ||||||
|  | 
 | ||||||
|  |           originalDerived = (DerivedReferenceType)original.DerivedProperty; | ||||||
|  |           clonedDerived = (DerivedReferenceType)clone.DerivedProperty; | ||||||
|  |           Assert.AreEqual(originalDerived.TestField, clonedDerived.TestField); | ||||||
|  |           Assert.AreEqual(originalDerived.TestProperty, clonedDerived.TestProperty); | ||||||
|  |           Assert.AreEqual(originalDerived.DerivedField, clonedDerived.DerivedField); | ||||||
|  |           Assert.AreEqual(originalDerived.DerivedProperty, clonedDerived.DerivedProperty); | ||||||
|  | 
 | ||||||
|           Assert.AreNotSame( |           Assert.AreNotSame( | ||||||
|             original.ReferenceTypeArrayField, clone.ReferenceTypeArrayField |             original.ReferenceTypeArrayField, clone.ReferenceTypeArrayField | ||||||
|           ); |           ); | ||||||
|  | @ -238,6 +289,8 @@ namespace Nuclex.Support.Cloning { | ||||||
|             clone.ReferenceTypeArrayProperty[1, 3][2].TestField |             clone.ReferenceTypeArrayProperty[1, 3][2].TestField | ||||||
|           ); |           ); | ||||||
|         } else { |         } else { | ||||||
|  |           Assert.AreSame(original.DerivedField, clone.DerivedField); | ||||||
|  |           Assert.AreSame(original.DerivedProperty, clone.DerivedProperty); | ||||||
|           Assert.AreSame(original.ReferenceTypeField, clone.ReferenceTypeField); |           Assert.AreSame(original.ReferenceTypeField, clone.ReferenceTypeField); | ||||||
|           Assert.AreSame(original.ReferenceTypeProperty, clone.ReferenceTypeProperty); |           Assert.AreSame(original.ReferenceTypeProperty, clone.ReferenceTypeProperty); | ||||||
|           Assert.AreSame( |           Assert.AreSame( | ||||||
|  | @ -248,22 +301,6 @@ namespace Nuclex.Support.Cloning { | ||||||
|           ); |           ); | ||||||
|         } |         } | ||||||
|       } |       } | ||||||
| 
 |  | ||||||
|       Assert.AreEqual(original.TestProperty, clone.TestProperty); |  | ||||||
|       Assert.AreEqual( |  | ||||||
|         original.ValueTypeProperty.TestProperty, clone.ValueTypeProperty.TestProperty |  | ||||||
|       ); |  | ||||||
|       Assert.AreEqual( |  | ||||||
|         original.ReferenceTypeProperty.TestProperty, clone.ReferenceTypeProperty.TestProperty |  | ||||||
|       ); |  | ||||||
|       Assert.AreEqual( |  | ||||||
|         original.ReferenceTypeArrayProperty[1, 3][0].TestProperty, |  | ||||||
|         clone.ReferenceTypeArrayProperty[1, 3][0].TestProperty |  | ||||||
|       ); |  | ||||||
|       Assert.AreEqual( |  | ||||||
|         original.ReferenceTypeArrayProperty[1, 3][2].TestProperty, |  | ||||||
|         clone.ReferenceTypeArrayProperty[1, 3][2].TestProperty |  | ||||||
|       ); |  | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     /// <summary> |     /// <summary> | ||||||
|  | @ -286,12 +323,21 @@ namespace Nuclex.Support.Cloning { | ||||||
|         Assert.AreEqual(0, clone.ValueTypeField.TestProperty); |         Assert.AreEqual(0, clone.ValueTypeField.TestProperty); | ||||||
|         Assert.AreEqual(0, clone.ValueTypeProperty.TestField); |         Assert.AreEqual(0, clone.ValueTypeProperty.TestField); | ||||||
|         Assert.IsNull(clone.ReferenceTypeField); |         Assert.IsNull(clone.ReferenceTypeField); | ||||||
|  |         Assert.IsNull(clone.DerivedField); | ||||||
| 
 | 
 | ||||||
|         if(isDeepClone) { |         if(isDeepClone) { | ||||||
|           Assert.AreNotSame(original.ReferenceTypeProperty, clone.ReferenceTypeProperty); |           Assert.AreNotSame(original.ReferenceTypeProperty, clone.ReferenceTypeProperty); | ||||||
|           Assert.AreNotSame( |           Assert.AreNotSame( | ||||||
|             original.ReferenceTypeArrayProperty, clone.ReferenceTypeArrayProperty |             original.ReferenceTypeArrayProperty, clone.ReferenceTypeArrayProperty | ||||||
|           ); |           ); | ||||||
|  |           Assert.AreNotSame(original.DerivedProperty, clone.DerivedProperty); | ||||||
|  |           Assert.IsInstanceOf<DerivedReferenceType>(clone.DerivedProperty); | ||||||
|  | 
 | ||||||
|  |           var originalDerived = (DerivedReferenceType)original.DerivedProperty; | ||||||
|  |           var clonedDerived = (DerivedReferenceType)clone.DerivedProperty; | ||||||
|  |           Assert.AreEqual(originalDerived.TestProperty, clonedDerived.TestProperty); | ||||||
|  |           Assert.AreEqual(originalDerived.DerivedProperty, clonedDerived.DerivedProperty); | ||||||
|  | 
 | ||||||
|           Assert.AreEqual(0, clone.ReferenceTypeProperty.TestField); |           Assert.AreEqual(0, clone.ReferenceTypeProperty.TestField); | ||||||
|           Assert.AreNotSame( |           Assert.AreNotSame( | ||||||
|             original.ReferenceTypeArrayProperty[1, 3][0], |             original.ReferenceTypeArrayProperty[1, 3][0], | ||||||
|  | @ -304,6 +350,7 @@ namespace Nuclex.Support.Cloning { | ||||||
|           Assert.AreEqual(0, clone.ReferenceTypeArrayProperty[1, 3][0].TestField); |           Assert.AreEqual(0, clone.ReferenceTypeArrayProperty[1, 3][0].TestField); | ||||||
|           Assert.AreEqual(0, clone.ReferenceTypeArrayProperty[1, 3][2].TestField); |           Assert.AreEqual(0, clone.ReferenceTypeArrayProperty[1, 3][2].TestField); | ||||||
|         } else { |         } else { | ||||||
|  |           Assert.AreSame(original.ReferenceTypeProperty, clone.ReferenceTypeProperty); | ||||||
|           Assert.AreSame(original.ReferenceTypeProperty, clone.ReferenceTypeProperty); |           Assert.AreSame(original.ReferenceTypeProperty, clone.ReferenceTypeProperty); | ||||||
|           Assert.AreSame( |           Assert.AreSame( | ||||||
|             original.ReferenceTypeArrayProperty, clone.ReferenceTypeArrayProperty |             original.ReferenceTypeArrayProperty, clone.ReferenceTypeArrayProperty | ||||||
|  | @ -329,6 +376,25 @@ namespace Nuclex.Support.Cloning { | ||||||
|         if(isDeepClone) { |         if(isDeepClone) { | ||||||
|           Assert.AreNotSame(original.ReferenceTypeField, clone.ReferenceTypeField); |           Assert.AreNotSame(original.ReferenceTypeField, clone.ReferenceTypeField); | ||||||
|           Assert.AreNotSame(original.ReferenceTypeProperty, clone.ReferenceTypeProperty); |           Assert.AreNotSame(original.ReferenceTypeProperty, clone.ReferenceTypeProperty); | ||||||
|  |           Assert.AreNotSame(original.DerivedField, clone.DerivedField); | ||||||
|  |           Assert.AreNotSame(original.DerivedProperty, clone.DerivedProperty); | ||||||
|  |           Assert.IsInstanceOf<DerivedReferenceType>(clone.DerivedField); | ||||||
|  |           Assert.IsInstanceOf<DerivedReferenceType>(clone.DerivedProperty); | ||||||
|  | 
 | ||||||
|  |           var originalDerived = (DerivedReferenceType)original.DerivedField; | ||||||
|  |           var clonedDerived = (DerivedReferenceType)clone.DerivedField; | ||||||
|  |           Assert.AreEqual(originalDerived.TestField, clonedDerived.TestField); | ||||||
|  |           Assert.AreEqual(originalDerived.TestProperty, clonedDerived.TestProperty); | ||||||
|  |           Assert.AreEqual(originalDerived.DerivedField, clonedDerived.DerivedField); | ||||||
|  |           Assert.AreEqual(originalDerived.DerivedProperty, clonedDerived.DerivedProperty); | ||||||
|  | 
 | ||||||
|  |           originalDerived = (DerivedReferenceType)original.DerivedProperty; | ||||||
|  |           clonedDerived = (DerivedReferenceType)clone.DerivedProperty; | ||||||
|  |           Assert.AreEqual(originalDerived.TestField, clonedDerived.TestField); | ||||||
|  |           Assert.AreEqual(originalDerived.TestProperty, clonedDerived.TestProperty); | ||||||
|  |           Assert.AreEqual(originalDerived.DerivedField, clonedDerived.DerivedField); | ||||||
|  |           Assert.AreEqual(originalDerived.DerivedProperty, clonedDerived.DerivedProperty); | ||||||
|  | 
 | ||||||
|           Assert.AreNotSame( |           Assert.AreNotSame( | ||||||
|             original.ReferenceTypeArrayField, clone.ReferenceTypeArrayField |             original.ReferenceTypeArrayField, clone.ReferenceTypeArrayField | ||||||
|           ); |           ); | ||||||
|  | @ -352,6 +418,8 @@ namespace Nuclex.Support.Cloning { | ||||||
|             clone.ReferenceTypeArrayProperty[1, 3][2].TestField |             clone.ReferenceTypeArrayProperty[1, 3][2].TestField | ||||||
|           ); |           ); | ||||||
|         } else { |         } else { | ||||||
|  |           Assert.AreSame(original.DerivedField, clone.DerivedField); | ||||||
|  |           Assert.AreSame(original.DerivedProperty, clone.DerivedProperty); | ||||||
|           Assert.AreSame(original.ReferenceTypeField, clone.ReferenceTypeField); |           Assert.AreSame(original.ReferenceTypeField, clone.ReferenceTypeField); | ||||||
|           Assert.AreSame(original.ReferenceTypeProperty, clone.ReferenceTypeProperty); |           Assert.AreSame(original.ReferenceTypeProperty, clone.ReferenceTypeProperty); | ||||||
|           Assert.AreSame( |           Assert.AreSame( | ||||||
|  | @ -427,6 +495,18 @@ namespace Nuclex.Support.Cloning { | ||||||
|         ReferenceTypeProperty = new TestReferenceType() { |         ReferenceTypeProperty = new TestReferenceType() { | ||||||
|           TestField = 246, |           TestField = 246, | ||||||
|           TestProperty = 642, |           TestProperty = 642, | ||||||
|  |         }, | ||||||
|  |         DerivedField = new DerivedReferenceType() { | ||||||
|  |           DerivedField = 100, | ||||||
|  |           DerivedProperty = 200, | ||||||
|  |           TestField = 300, | ||||||
|  |           TestProperty = 400 | ||||||
|  |         }, | ||||||
|  |         DerivedProperty = new DerivedReferenceType() { | ||||||
|  |           DerivedField = 500, | ||||||
|  |           DerivedProperty = 600, | ||||||
|  |           TestField = 700, | ||||||
|  |           TestProperty = 800 | ||||||
|         } |         } | ||||||
|       }; |       }; | ||||||
|     } |     } | ||||||
|  | @ -478,6 +558,18 @@ namespace Nuclex.Support.Cloning { | ||||||
|         ReferenceTypeProperty = new TestReferenceType() { |         ReferenceTypeProperty = new TestReferenceType() { | ||||||
|           TestField = 246, |           TestField = 246, | ||||||
|           TestProperty = 642, |           TestProperty = 642, | ||||||
|  |         }, | ||||||
|  |         DerivedField = new DerivedReferenceType() { | ||||||
|  |           DerivedField = 100, | ||||||
|  |           DerivedProperty = 200, | ||||||
|  |           TestField = 300, | ||||||
|  |           TestProperty = 400 | ||||||
|  |         }, | ||||||
|  |         DerivedProperty = new DerivedReferenceType() { | ||||||
|  |           DerivedField = 500, | ||||||
|  |           DerivedProperty = 600, | ||||||
|  |           TestField = 700, | ||||||
|  |           TestProperty = 800 | ||||||
|         } |         } | ||||||
|       }; |       }; | ||||||
|     } |     } | ||||||
|  |  | ||||||
							
								
								
									
										74
									
								
								Source/Cloning/ClonerHelpers.Test.cs
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										74
									
								
								Source/Cloning/ClonerHelpers.Test.cs
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,74 @@ | ||||||
|  | #region CPL License | ||||||
|  | /* | ||||||
|  | Nuclex Framework | ||||||
|  | Copyright (C) 2002-2010 Nuclex Development Labs | ||||||
|  | 
 | ||||||
|  | This library is free software; you can redistribute it and/or | ||||||
|  | modify it under the terms of the IBM Common Public License as | ||||||
|  | published by the IBM Corporation; either version 1.0 of the | ||||||
|  | License, or (at your option) any later version. | ||||||
|  | 
 | ||||||
|  | This library is distributed in the hope that it will be useful, | ||||||
|  | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||||
|  | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||||||
|  | IBM Common Public License for more details. | ||||||
|  | 
 | ||||||
|  | You should have received a copy of the IBM Common Public | ||||||
|  | License along with this library | ||||||
|  | */ | ||||||
|  | #endregion | ||||||
|  | 
 | ||||||
|  | #if UNITTEST | ||||||
|  | 
 | ||||||
|  | using System; | ||||||
|  | using System.Reflection; | ||||||
|  | 
 | ||||||
|  | using NUnit.Framework; | ||||||
|  | 
 | ||||||
|  | namespace Nuclex.Support.Cloning { | ||||||
|  | 
 | ||||||
|  |   /// <summary>Unit Test for the cloner helpers</summary> | ||||||
|  |   [TestFixture] | ||||||
|  |   internal class ClonerHelpersTest { | ||||||
|  | 
 | ||||||
|  |     #region class Base | ||||||
|  | 
 | ||||||
|  |     /// <summary>Base class used to test the helper methods</summary> | ||||||
|  |     private class Base { | ||||||
|  |       /// <summary>A simple public field</summary> | ||||||
|  |       public int PublicBaseField; | ||||||
|  |       /// <summary>An automatic property with a hidden backing field</summary> | ||||||
|  |       public int PublicBaseProperty { get; set; } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     #endregion // class Base | ||||||
|  | 
 | ||||||
|  |     #region class Derived | ||||||
|  | 
 | ||||||
|  |     /// <summary>Derived class used to test the helper methods</summary> | ||||||
|  |     private class Derived : Base { | ||||||
|  |       /// <summary>A simple public field</summary> | ||||||
|  |       public int PublicDerivedField; | ||||||
|  |       /// <summary>An automatic property with a hidden backing field</summary> | ||||||
|  |       public int PublicDerivedProperty { get; set; } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     #endregion // class Derived | ||||||
|  | 
 | ||||||
|  |     /// <summary> | ||||||
|  |     ///   Verifies that the GetFieldInfosIncludingBaseClasses() will include the backing | ||||||
|  |     ///   fields of automatically implemented properties in base classes | ||||||
|  |     /// </summary> | ||||||
|  |     [Test] | ||||||
|  |     public void CanGetBackingFieldsForPropertiesInBaseClasses() { | ||||||
|  |       FieldInfo[] fieldInfos = ClonerHelpers.GetFieldInfosIncludingBaseClasses( | ||||||
|  |         typeof(Derived), BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | ||||||
|  |       ); | ||||||
|  |       Assert.AreEqual(4, fieldInfos.Length); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  | } // namespace Nuclex.Support.Cloning | ||||||
|  | 
 | ||||||
|  | #endif // UNITTEST | ||||||
							
								
								
									
										81
									
								
								Source/Cloning/ClonerHelpers.cs
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										81
									
								
								Source/Cloning/ClonerHelpers.cs
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,81 @@ | ||||||
|  | #region CPL License | ||||||
|  | /* | ||||||
|  | Nuclex Framework | ||||||
|  | Copyright (C) 2002-2010 Nuclex Development Labs | ||||||
|  | 
 | ||||||
|  | This library is free software; you can redistribute it and/or | ||||||
|  | modify it under the terms of the IBM Common Public License as | ||||||
|  | published by the IBM Corporation; either version 1.0 of the | ||||||
|  | License, or (at your option) any later version. | ||||||
|  | 
 | ||||||
|  | This library is distributed in the hope that it will be useful, | ||||||
|  | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||||
|  | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||||||
|  | IBM Common Public License for more details. | ||||||
|  | 
 | ||||||
|  | You should have received a copy of the IBM Common Public | ||||||
|  | License along with this library | ||||||
|  | */ | ||||||
|  | #endregion | ||||||
|  | 
 | ||||||
|  | using System; | ||||||
|  | using System.Collections.Generic; | ||||||
|  | using System.Linq; | ||||||
|  | using System.Text; | ||||||
|  | using System.Reflection; | ||||||
|  | 
 | ||||||
|  | namespace Nuclex.Support.Cloning { | ||||||
|  | 
 | ||||||
|  |   /// <summary>Contains helper methods for the cloners</summary> | ||||||
|  |   internal static class ClonerHelpers { | ||||||
|  | 
 | ||||||
|  |     /// <summary> | ||||||
|  |     ///   Returns all the fields of a type, working around a weird reflection issue | ||||||
|  |     ///   where explicitly declared fields in base classes are returned, but not | ||||||
|  |     ///   automatic property backing fields. | ||||||
|  |     /// </summary> | ||||||
|  |     /// <param name="type">Type whose fields will be returned</param> | ||||||
|  |     /// <param name="bindingFlags">Binding flags to use when querying the fields</param> | ||||||
|  |     /// <returns>All of the type's fields, including its base types</returns> | ||||||
|  |     public static FieldInfo[] GetFieldInfosIncludingBaseClasses( | ||||||
|  |       Type type, BindingFlags bindingFlags | ||||||
|  |     ) { | ||||||
|  |       FieldInfo[] fieldInfos = type.GetFields(bindingFlags); | ||||||
|  | 
 | ||||||
|  |       // If this class doesn't have a base, don't waste any time | ||||||
|  |       if(type.BaseType == typeof(object)) { | ||||||
|  |         return fieldInfos; | ||||||
|  |       } else { // Otherwise, collect all types up to the furthest base class | ||||||
|  |         var fieldInfoList = new List<FieldInfo>(fieldInfos); | ||||||
|  |         while(type.BaseType != typeof(object)) { | ||||||
|  |           type = type.BaseType; | ||||||
|  |           fieldInfos = type.GetFields(bindingFlags); | ||||||
|  | 
 | ||||||
|  |           // Look for fields we do not have listed yet and merge them into the main list | ||||||
|  |           for(int index = 0; index < fieldInfos.Length; ++index) { | ||||||
|  |             bool found = false; | ||||||
|  | 
 | ||||||
|  |             for(int searchIndex = 0; searchIndex < fieldInfoList.Count; ++searchIndex) { | ||||||
|  |               bool match = | ||||||
|  |                 (fieldInfoList[searchIndex].DeclaringType == fieldInfos[index].DeclaringType) && | ||||||
|  |                 (fieldInfoList[searchIndex].Name == fieldInfos[index].Name); | ||||||
|  | 
 | ||||||
|  |               if(match) { | ||||||
|  |                 found = true; | ||||||
|  |                 break; | ||||||
|  |               } | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             if(!found) { | ||||||
|  |               fieldInfoList.Add(fieldInfos[index]); | ||||||
|  |             } | ||||||
|  |           } | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         return fieldInfoList.ToArray(); | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  | } // namespace Nuclex.Support.Cloning | ||||||
|  | @ -185,9 +185,8 @@ namespace Nuclex.Support.Cloning { | ||||||
|         ); |         ); | ||||||
| 
 | 
 | ||||||
|         // Enumerate all of the type's fields and generate transfer expressions for each |         // Enumerate all of the type's fields and generate transfer expressions for each | ||||||
|         FieldInfo[] fieldInfos = clonedType.GetFields( |         FieldInfo[] fieldInfos = ClonerHelpers.GetFieldInfosIncludingBaseClasses( | ||||||
|           BindingFlags.Public | BindingFlags.NonPublic | |           clonedType, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | ||||||
|           BindingFlags.Instance | BindingFlags.FlattenHierarchy |  | ||||||
|         ); |         ); | ||||||
|         for(int index = 0; index < fieldInfos.Length; ++index) { |         for(int index = 0; index < fieldInfos.Length; ++index) { | ||||||
|           FieldInfo fieldInfo = fieldInfos[index]; |           FieldInfo fieldInfo = fieldInfos[index]; | ||||||
|  | @ -462,9 +461,9 @@ namespace Nuclex.Support.Cloning { | ||||||
|       ICollection<Expression> transferExpressions |       ICollection<Expression> transferExpressions | ||||||
|     ) { |     ) { | ||||||
|       // Enumerate all of the type's fields and generate transfer expressions for each |       // Enumerate all of the type's fields and generate transfer expressions for each | ||||||
|       FieldInfo[] fieldInfos = clonedType.GetFields( |       FieldInfo[] fieldInfos = ClonerHelpers.GetFieldInfosIncludingBaseClasses( | ||||||
|         BindingFlags.Public | BindingFlags.NonPublic | |         clonedType, | ||||||
|         BindingFlags.Instance | BindingFlags.FlattenHierarchy |         BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | ||||||
|       ); |       ); | ||||||
|       for(int index = 0; index < fieldInfos.Length; ++index) { |       for(int index = 0; index < fieldInfos.Length; ++index) { | ||||||
|         FieldInfo fieldInfo = fieldInfos[index]; |         FieldInfo fieldInfo = fieldInfos[index]; | ||||||
|  |  | ||||||
|  | @ -29,7 +29,7 @@ namespace Nuclex.Support.Cloning { | ||||||
| 
 | 
 | ||||||
|   /// <summary>Unit Test for the expression tree-based cloner</summary> |   /// <summary>Unit Test for the expression tree-based cloner</summary> | ||||||
|   [TestFixture] |   [TestFixture] | ||||||
|   internal class ExpressionTreeClonerTest : CloneFactoryTest { |   public class ExpressionTreeClonerTest : CloneFactoryTest { | ||||||
| 
 | 
 | ||||||
|     /// <summary>Initializes a new unit test suite for the reflection cloner</summary> |     /// <summary>Initializes a new unit test suite for the reflection cloner</summary> | ||||||
|     public ExpressionTreeClonerTest() { |     public ExpressionTreeClonerTest() { | ||||||
|  |  | ||||||
|  | @ -167,9 +167,8 @@ namespace Nuclex.Support.Cloning { | ||||||
|       object clone = FormatterServices.GetUninitializedObject(originalType); |       object clone = FormatterServices.GetUninitializedObject(originalType); | ||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
|       FieldInfo[] fieldInfos = originalType.GetFields( |       FieldInfo[] fieldInfos = ClonerHelpers.GetFieldInfosIncludingBaseClasses( | ||||||
|         BindingFlags.Public | BindingFlags.NonPublic | |         originalType, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | ||||||
|         BindingFlags.Instance | BindingFlags.FlattenHierarchy |  | ||||||
|       ); |       ); | ||||||
|       for(int index = 0; index < fieldInfos.Length; ++index) { |       for(int index = 0; index < fieldInfos.Length; ++index) { | ||||||
|         FieldInfo fieldInfo = fieldInfos[index]; |         FieldInfo fieldInfo = fieldInfos[index]; | ||||||
|  | @ -250,9 +249,8 @@ namespace Nuclex.Support.Cloning { | ||||||
|       object clone = FormatterServices.GetUninitializedObject(originalType); |       object clone = FormatterServices.GetUninitializedObject(originalType); | ||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
|       FieldInfo[] fieldInfos = originalType.GetFields( |       FieldInfo[] fieldInfos = ClonerHelpers.GetFieldInfosIncludingBaseClasses( | ||||||
|         BindingFlags.Public | BindingFlags.NonPublic | |         originalType, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | ||||||
|         BindingFlags.Instance | BindingFlags.FlattenHierarchy |  | ||||||
|       ); |       ); | ||||||
|       for(int index = 0; index < fieldInfos.Length; ++index) { |       for(int index = 0; index < fieldInfos.Length; ++index) { | ||||||
|         FieldInfo fieldInfo = fieldInfos[index]; |         FieldInfo fieldInfo = fieldInfos[index]; | ||||||
|  |  | ||||||
|  | @ -118,9 +118,8 @@ namespace Nuclex.Support.Cloning { | ||||||
|       ) { |       ) { | ||||||
|         Type originalType = objectToSerialize.GetType(); |         Type originalType = objectToSerialize.GetType(); | ||||||
| 
 | 
 | ||||||
|         FieldInfo[] fieldInfos = originalType.GetFields( |         FieldInfo[] fieldInfos = ClonerHelpers.GetFieldInfosIncludingBaseClasses( | ||||||
|           BindingFlags.Public | BindingFlags.NonPublic | |           originalType, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | ||||||
|           BindingFlags.Instance | BindingFlags.FlattenHierarchy |  | ||||||
|         ); |         ); | ||||||
|         for(int index = 0; index < fieldInfos.Length; ++index) { |         for(int index = 0; index < fieldInfos.Length; ++index) { | ||||||
|           FieldInfo fieldInfo = fieldInfos[index]; |           FieldInfo fieldInfo = fieldInfos[index]; | ||||||
|  | @ -144,9 +143,8 @@ namespace Nuclex.Support.Cloning { | ||||||
|       ) { |       ) { | ||||||
|         Type originalType = deserializedObject.GetType(); |         Type originalType = deserializedObject.GetType(); | ||||||
| 
 | 
 | ||||||
|         FieldInfo[] fieldInfos = originalType.GetFields( |         FieldInfo[] fieldInfos = ClonerHelpers.GetFieldInfosIncludingBaseClasses( | ||||||
|           BindingFlags.Public | BindingFlags.NonPublic | |           originalType, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | ||||||
|           BindingFlags.Instance | BindingFlags.FlattenHierarchy |  | ||||||
|         ); |         ); | ||||||
|         for(int index = 0; index < fieldInfos.Length; ++index) { |         for(int index = 0; index < fieldInfos.Length; ++index) { | ||||||
|           FieldInfo fieldInfo = fieldInfos[index]; |           FieldInfo fieldInfo = fieldInfos[index]; | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue