Different Method To Clone An Object

  1. class Program  
  2. {  
  3.     ///  
  4.    
  5. <summary>  
  6.     /// Delegate handler that's used to compile the IL to.  
  7.     /// (This delegate is standard in .net 3.5)  
  8.     /// </summary>  
  9.    
  10.    
  11.     /// <typeparam name="T1">Parameter Type</typeparam>  
  12.     /// <typeparam name="TResult">Return Type</typeparam>  
  13.     /// <param name="arg1">Argument</param>  
  14.     /// <returns>Result</returns>  
  15.     public delegate TResult Func<T1, TResult>(T1 arg1);  
  16.     ///  
  17.    
  18. <summary>  
  19.     /// This dictionary caches the delegates for each 'to-clone' type.  
  20.     /// </summary>  
  21.    
  22.    
  23.     static Dictionary<Type, Delegate> _cachedIL = new Dictionary<Type, Delegate>();  
  24.    
  25.     ///  
  26.    
  27. <summary>  
  28.     /// The Main method that's executed for the test.  
  29.     /// </summary>  
  30.    
  31.    
  32.     /// <param name="args"></param>  
  33.     static void Main(string[] args)  
  34.     {  
  35.         DoCloningTest(1000);  
  36.         DoCloningTest(10000);  
  37.         DoCloningTest(100000);  
  38.         //Commented because the test takes long <img class="emoji" draggable="false" alt="??" src="https://s0.wp.com/wp-content/mu-plugins/wpcom-smileys/twemoji/2/svg/1f609.svg">  
  39.         //DoCloningTest(1000000);  
  40.    
  41.         Console.ReadKey();  
  42.     }  
  43.    
  44.     ///  
  45.    
  46. <summary>  
  47.     /// Do the cloning test and printout the results.  
  48.     /// </summary>  
  49.    
  50.    
  51.     /// <param name="count">Number of items to clone</param>  
  52.     private static void DoCloningTest(int count)  
  53.     {  
  54.         // Create timer class.  
  55.         HiPerfTimer timer = new HiPerfTimer();  
  56.         double timeElapsedN = 0, timeElapsedR = 0, timeElapsedIL = 0;  
  57.    
  58.         Console.WriteLine("--> Creating {0} objects...", count);  
  59.         timer.StartNew();  
  60.         List<Person> personsToClone = CreatePersonsList(count);  
  61.         timer.Stop();  
  62.         Person temp = CloneObjectWithIL(personsToClone[0]);  
  63.         temp = null;  
  64.         Console.WriteLine("\tCreated objects in {0} seconds", timer.Duration);  
  65.    
  66.         Console.WriteLine("- Cloning Normal...");  
  67.         List<Person> clonedPersons = new List<Person>(count);  
  68.         timer.StartNew();  
  69.         foreach (Person p in personsToClone)  
  70.         {  
  71.             clonedPersons.Add(CloneNormal(p));  
  72.         }  
  73.         timer.Stop();  
  74.         timeElapsedN = timer.Duration;  
  75.    
  76.         Console.WriteLine("- Cloning IL...");  
  77.         clonedPersons = new List<Person>(count);  
  78.         timer.StartNew();  
  79.         foreach (Person p in personsToClone)  
  80.         {  
  81.             clonedPersons.Add(CloneObjectWithIL<Person>(p));  
  82.         }  
  83.         timer.Stop();  
  84.         timeElapsedIL = timer.Duration;  
  85.    
  86.         Console.WriteLine("- Cloning Reflection...");  
  87.         clonedPersons = new List<Person>(count);  
  88.         timer.StartNew();  
  89.         foreach (Person p in personsToClone)  
  90.         {  
  91.             clonedPersons.Add(CloneObjectWithReflection(p));  
  92.         }  
  93.         timer.Stop();  
  94.         timeElapsedR = timer.Duration;  
  95.    
  96.         Console.WriteLine();  
  97.         Console.ForegroundColor = ConsoleColor.Green;  
  98.         Console.WriteLine("----------------------------------------");  
  99.         Console.WriteLine("Object count:\t\t{0}", count);  
  100.         Console.WriteLine("Cloning Normal:\t\t{0:00.0000} s", timeElapsedN);  
  101.         Console.WriteLine("Cloning IL:\t\t{0:00.0000} s", timeElapsedIL);  
  102.         Console.WriteLine("Cloning Reflection:\t{0:00.0000} s", timeElapsedR);  
  103.         Console.WriteLine("----------------------------------------");  
  104.         Console.ResetColor();  
  105.     }  
  106.    
  107.     ///  
  108.    
  109. <summary>  
  110.     /// Create a list of persons with random data and a given number of items.  
  111.     /// </summary>  
  112.    
  113.    
  114.     /// <param name="count">Number of persons to generate</param>  
  115.     /// <returns>List of generated persons</returns>  
  116.     private static List<Person> CreatePersonsList(int count)  
  117.     {  
  118.         Random r = new Random(Environment.TickCount);  
  119.         List<Person> persons = new List<Person>(count);  
  120.         for (int i = 0; i < count; i++)  
  121.         {  
  122.             Person p = new Person();  
  123.             p.ID = r.Next();  
  124.             p.Name = string.Concat("Slaets_", r.Next());  
  125.             p.FirstName = string.Concat("Filip_", r.Next());  
  126.             persons.Add(p);  
  127.         }  
  128.         return persons;  
  129.     }  
  130.    
  131.     ///  
  132.    
  133. <summary>  
  134.     /// Clone one person object with reflection  
  135.     /// </summary>  
  136.    
  137.    
  138.     /// <param name="p">Person to clone</param>  
  139.     /// <returns>Cloned person</returns>  
  140.     private static Person CloneObjectWithReflection(Person p)  
  141.     {  
  142.         // Get all the fields of the type, also the privates.  
  143.         FieldInfo[] fis = p.GetType().GetFields(System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.NonPublic);  
  144.         // Create a new person object  
  145.         Person newPerson = new Person();  
  146.         // Loop through all the fields and copy the information from the parameter class  
  147.         // to the newPerson class.  
  148.         foreach (FieldInfo fi in fis)  
  149.         {  
  150.             fi.SetValue(newPerson, fi.GetValue(p));  
  151.         }  
  152.         // Return the cloned object.  
  153.         return newPerson;  
  154.     }  
  155.    
  156.     ///  
  157.    
  158. <summary>  
  159.     /// Generic cloning method that clones an object using IL.  
  160.     /// Only the first call of a certain type will hold back performance.  
  161.     /// After the first call, the compiled IL is executed.  
  162.     /// </summary>  
  163.    
  164.    
  165.     /// <typeparam name="T">Type of object to clone</typeparam>  
  166.     /// <param name="myObject">Object to clone</param>  
  167.     /// <returns>Cloned object</returns>  
  168.     private static T CloneObjectWithIL<T>(T myObject)  
  169.     {  
  170.         Delegate myExec = null;  
  171.         if (!_cachedIL.TryGetValue(typeof(T), out myExec))  
  172.         {  
  173.             // Create ILGenerator  
  174.             DynamicMethod dymMethod = new DynamicMethod("DoClone"typeof(T), new Type[] { typeof(T) }, true);  
  175.             ConstructorInfo cInfo = myObject.GetType().GetConstructor(new Type[] { });  
  176.    
  177.             ILGenerator generator = dymMethod.GetILGenerator();  
  178.    
  179.             LocalBuilder lbf = generator.DeclareLocal(typeof(T));  
  180.             //lbf.SetLocalSymInfo("_temp");  
  181.    
  182.             generator.Emit(OpCodes.Newobj, cInfo);  
  183.             generator.Emit(OpCodes.Stloc_0);  
  184.             foreach (FieldInfo field in myObject.GetType().GetFields(System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.NonPublic))  
  185.             {  
  186.                 // Load the new object on the eval stack... (currently 1 item on eval stack)  
  187.                 generator.Emit(OpCodes.Ldloc_0);  
  188.                 // Load initial object (parameter)          (currently 2 items on eval stack)  
  189.                 generator.Emit(OpCodes.Ldarg_0);  
  190.                 // Replace value by field value             (still currently 2 items on eval stack)  
  191.                 generator.Emit(OpCodes.Ldfld, field);  
  192.                 // Store the value of the top on the eval stack into the object underneath that value on the value stack.  
  193.                 //  (0 items on eval stack)  
  194.                 generator.Emit(OpCodes.Stfld, field);  
  195.             }  
  196.                
  197.             // Load new constructed obj on eval stack -> 1 item on stack  
  198.             generator.Emit(OpCodes.Ldloc_0);  
  199.             // Return constructed object.   --> 0 items on stack  
  200.             generator.Emit(OpCodes.Ret);  
  201.    
  202.             myExec = dymMethod.CreateDelegate(typeof(Func<T, T>));  
  203.             _cachedIL.Add(typeof(T), myExec);  
  204.         }  
  205.         return ((Func<T, T>)myExec)(myObject);  
  206.     }  
  207.    
  208.     ///  
  209.    
  210. <summary>  
  211.     /// Clone a person object by manually typing the copy statements.  
  212.     /// </summary>  
  213.    
  214.    
  215.     /// <param name="p">Object to clone</param>  
  216.     /// <returns>Cloned object</returns>  
  217.     private static Person CloneNormal(Person p)  
  218.     {  
  219.         Person newPerson = new Person();  
  220.         newPerson.ID = p.ID;  
  221.         newPerson.Name = p.Name;  
  222.         newPerson.FirstName = p.FirstName;  
  223.         return newPerson;  
  224.     }  
  225. }  
  226.    
Different ways of Object Cloning 

Object Cloning is broadly categorized into Shallow copy and Deep copy. This article is not about shallow Copy and deep copy so will just give a brief introduction.

Shallow Copy

Copy the reference but not referenced object.

Deep Copy

Copy the reference and referenced objects.

Multiple ways to create clone of Object,

Clone Manually (ICloneable Interface)

This is simple but not ra ecommended way to create object as it does not specify if the object cloning is done by Deep copy approach or Shallow copy approach.
  1. using System;  
  2.    
  3. class Rock : ICloneable  
  4. {  
  5.     int _weight;  
  6.     bool _round;  
  7.     bool _mossy;  
  8.    
  9.     public Rock(int weight, bool round, bool mossy)  
  10.     {  
  11.         this._weight = weight;  
  12.         this._round = round;  
  13.         this._mossy = mossy;  
  14.     }  
  15.     public object Clone()  
  16.     {  
  17.         return new Rock(this._weight, this._round, this._mossy);  
  18.     }  
  19.    
  20.     public override string ToString()  
  21.     {  
  22.         return string.Format("weight = {0}, round = {1}, mossy = {2}",  
  23.             this._weight,  
  24.             this._round,  
  25.             this._mossy);  
  26.     }  
  27. }  
  28. class Program  
  29. {  
  30.     static void Main()  
  31.     {  
  32.         Rock rock1 = new Rock(10, truefalse);  
  33.         Rock rock2 = rock1.Clone() as Rock;  
  34.    
  35.         Console.WriteLine("1. {0}", rock1.ToString());  
  36.         Console.WriteLine("2. {0}", rock2.ToString());  
  37.         Console.ReadLine();  
  38.     }  
  39. }  

Clone using MemberwiseClone

  1. using System;  
  2.    
  3. class Rock   
  4. {  
  5.     int _weight;  
  6.     bool _round;  
  7.     bool _mossy;  
  8.    
  9.     public Rock(int weight, bool round, bool mossy)  
  10.     {  
  11.         this._weight = weight;  
  12.         this._round = round;  
  13.         this._mossy = mossy;  
  14.     }  
  15.    
  16.    
  17.     public Rock ShallowCopy()  
  18.     {  
  19.         return (Rock)this.MemberwiseClone();  
  20.     }  
  21.    
  22.    
  23.       
  24.    
  25.     public override string ToString()  
  26.     {  
  27.         return string.Format("weight = {0}, round = {1}, mossy = {2}",  
  28.             this._weight,  
  29.             this._round,  
  30.             this._mossy);  
  31.     }  
  32. }  
  33.    
  34. class Program  
  35. {  
  36.     static void Main()  
  37.     {  
  38.         Rock rock1 = new Rock(10, truefalse);  
  39.         Rock rock2 = rock1.ShallowCopy();  
  40.    
  41.         Console.WriteLine("1. {0}", rock1.ToString());  
  42.         Console.WriteLine("2. {0}", rock2.ToString());  
  43.         Console.ReadLine();  
  44.     }  
  45.  

Note

This is shallow copy using MemberwiseClone. This can be modified a bit to implement deep copy as well.

Clone with Reflection 
  1. using System;  
  2. using System.Reflection;  
  3. using System.Collections;  
  4.    
  5. namespace Amir_Harel.Cloning  
  6. {  
  7.     ///  
  8.    
  9.    
  10.    
  11. <summary>  
  12.     /// <b>BaseObject</b> class is an abstract class for you to derive from.   
  13.     /// Every class that will be dirived from this class will support the <b>Clone</b> method automaticly.  
  14.     /// The class implements the interface <i>ICloneable</i> and there for every object that will be derived   
  15.     /// from this object will support the <i>ICloneable</i> interface as well.  
  16.     /// </summary>  
  17.    
  18.    
  19.    
  20.    
  21.     public abstract class BaseObject : ICloneable  
  22.     {  
  23.         ///  
  24.    
  25.    
  26.    
  27. <summary>  
  28.         /// Clone the object, and returning a reference to a cloned object.  
  29.         /// </summary>  
  30.    
  31.    
  32.    
  33.    
  34.         /// <returns>Reference to the new cloned object.</returns>  
  35.         public object Clone()  
  36.         {  
  37.             //First we create an instance of this specific type.  
  38.             object newObject = Activator.CreateInstance(this.GetType());  
  39.    
  40.             //We get the array of fields for the new type instance.  
  41.             FieldInfo[] fields = newObject.GetType().GetFields();  
  42.    
  43.             int i = 0;  
  44.    
  45.             foreach (FieldInfo fi in this.GetType().GetFields())  
  46.             {  
  47.                 //We query if the fiels support the ICloneable interface.  
  48.                 Type ICloneType = fi.FieldType.GetInterface("ICloneable"true);  
  49.    
  50.                 if (ICloneType != null)  
  51.                 {  
  52.                     //Getting the ICloneable interface from the object.  
  53.                     ICloneable IClone = (ICloneable)fi.GetValue(this);  
  54.    
  55.                     //We use the clone method to set the new value to the field.  
  56.                     fields[i].SetValue(newObject, IClone.Clone());  
  57.                 }  
  58.                 else  
  59.                 {  
  60.                     //If the field doesn't support the ICloneable interface then just set it.  
  61.                     fields[i].SetValue(newObject, fi.GetValue(this));  
  62.                 }  
  63.    
  64.                 //Now we check if the object support the IEnumerable interface, so if it does  
  65.                 //we need to enumerate all its items and check if they support the ICloneable interface.  
  66.                 Type IEnumerableType = fi.FieldType.GetInterface("IEnumerable"true);  
  67.                 if (IEnumerableType != null)  
  68.                 {  
  69.                     //Get the IEnumerable interface from the field.  
  70.                     IEnumerable IEnum = (IEnumerable)fi.GetValue(this);  
  71.    
  72.                     //This version support the IList and the IDictionary interfaces to iterate  
  73.                     //on collections.  
  74.                     Type IListType = fields[i].FieldType.GetInterface("IList"true);  
  75.                     Type IDicType = fields[i].FieldType.GetInterface("IDictionary"true);  
  76.    
  77.                     int j = 0;  
  78.                     if (IListType != null)  
  79.                     {  
  80.                         //Getting the IList interface.  
  81.                         IList list = (IList)fields[i].GetValue(newObject);  
  82.    
  83.                         foreach (object obj in IEnum)  
  84.                         {  
  85.                             //Checking to see if the current item support the ICloneable interface.  
  86.                             ICloneType = obj.GetType().GetInterface("ICloneable"true);  
  87.    
  88.                             if (ICloneType != null)  
  89.                             {  
  90.                                 //If it does support the ICloneable interface, we use it to set the clone of  
  91.                                 //the object in the list.  
  92.                                 ICloneable clone = (ICloneable)obj;  
  93.    
  94.                                 list[j] = clone.Clone();  
  95.                             }  
  96.    
  97.                             //NOTE: If the item in the list is not support the ICloneable interface then  
  98.                             // in the cloned list this item will be the same item as in the original list  
  99.                             //(as long as this type is a reference type).  
  100.    
  101.                             j++;  
  102.                         }  
  103.                     }  
  104.                     else if (IDicType != null)  
  105.                     {  
  106.                         //Getting the dictionary interface.  
  107.                         IDictionary dic = (IDictionary)fields[i].GetValue(newObject);  
  108.                         j = 0;  
  109.                         foreach (DictionaryEntry de in IEnum)  
  110.                         {  
  111.                             //Checking to see if the item support the ICloneable interface.  
  112.                             ICloneType = de.Value.GetType().GetInterface("ICloneable"true);  
  113.    
  114.                             if (ICloneType != null)  
  115.                             {  
  116.                                 ICloneable clone = (ICloneable)de.Value;  
  117.    
  118.                                 dic[de.Key] = clone.Clone();  
  119.                             }  
  120.                             j++;  
  121.                         }  
  122.                     }  
  123.                 }  
  124.                 i++;  
  125.             }  
  126.             return newObject;  
  127.         }  
  128.     }  
  129. }  
Clone with Serialization  
  1. using System;  
  2. using System.IO;  
  3. using System.Runtime.Serialization;  
  4. using System.Runtime.Serialization.Formatters.Binary;          
  5. public static class ObjectClone  
  6. {  
  7.     public static T Clone<T>(T RealObject)  
  8.     {  
  9.         using (Stream objectStream = new MemoryStream())  
  10.         {  
  11.             IFormatter formatter = new BinaryFormatter();  
  12.             formatter.Serialize(objectStream, RealObject);  
  13.             objectStream.Seek(0, SeekOrigin.Begin);  
  14.             return (T)formatter.Deserialize(objectStream);  
  15.         }  
  16.     }  
  17. }   
Clone with IL
  1. class Program  
  2. {  
  3.     ///  
  4.    
  5. <summary>  
  6.     /// Delegate handler that's used to compile the IL to.  
  7.     /// (This delegate is standard in .net 3.5)  
  8.     /// </summary>  
  9.    
  10.    
  11.     /// <typeparam name="T1">Parameter Type</typeparam>  
  12.     /// <typeparam name="TResult">Return Type</typeparam>  
  13.     /// <param name="arg1">Argument</param>  
  14.     /// <returns>Result</returns>  
  15.     public delegate TResult Func<T1, TResult>(T1 arg1);  
  16.     ///  
  17.    
  18. <summary>  
  19.     /// This dictionary caches the delegates for each 'to-clone' type.  
  20.     /// </summary>  
  21.    
  22.    
  23.     static Dictionary<Type, Delegate> _cachedIL = new Dictionary<Type, Delegate>();  
  24.    
  25.     ///  
  26.    
  27. <summary>  
  28.     /// The Main method that's executed for the test.  
  29.     /// </summary>  
  30.    
  31.    
  32.     /// <param name="args"></param>  
  33.     static void Main(string[] args)  
  34.     {  
  35.         DoCloningTest(1000);  
  36.         DoCloningTest(10000);  
  37.         DoCloningTest(100000);  
  38.         //Commented because the test takes long <img class="emoji" draggable="false" alt="??" src="https://s0.wp.com/wp-content/mu-plugins/wpcom-smileys/twemoji/2/svg/1f609.svg">  
  39.         //DoCloningTest(1000000);  
  40.    
  41.         Console.ReadKey();  
  42.     }  
  43.    
  44.     ///  
  45.    
  46. <summary>  
  47.     /// Do the cloning test and printout the results.  
  48.     /// </summary>  
  49.    
  50.    
  51.     /// <param name="count">Number of items to clone</param>  
  52.     private static void DoCloningTest(int count)  
  53.     {  
  54.         // Create timer class.  
  55.         HiPerfTimer timer = new HiPerfTimer();  
  56.         double timeElapsedN = 0, timeElapsedR = 0, timeElapsedIL = 0;  
  57.    
  58.         Console.WriteLine("--> Creating {0} objects...", count);  
  59.         timer.StartNew();  
  60.         List<Person> personsToClone = CreatePersonsList(count);  
  61.         timer.Stop();  
  62.         Person temp = CloneObjectWithIL(personsToClone[0]);  
  63.         temp = null;  
  64.         Console.WriteLine("\tCreated objects in {0} seconds", timer.Duration);  
  65.    
  66.         Console.WriteLine("- Cloning Normal...");  
  67.         List<Person> clonedPersons = new List<Person>(count);  
  68.         timer.StartNew();  
  69.         foreach (Person p in personsToClone)  
  70.         {  
  71.             clonedPersons.Add(CloneNormal(p));  
  72.         }  
  73.         timer.Stop();  
  74.         timeElapsedN = timer.Duration;  
  75.    
  76.         Console.WriteLine("- Cloning IL...");  
  77.         clonedPersons = new List<Person>(count);  
  78.         timer.StartNew();  
  79.         foreach (Person p in personsToClone)  
  80.         {  
  81.             clonedPersons.Add(CloneObjectWithIL<Person>(p));  
  82.         }  
  83.         timer.Stop();  
  84.         timeElapsedIL = timer.Duration;  
  85.    
  86.         Console.WriteLine("- Cloning Reflection...");  
  87.         clonedPersons = new List<Person>(count);  
  88.         timer.StartNew();  
  89.         foreach (Person p in personsToClone)  
  90.         {  
  91.             clonedPersons.Add(CloneObjectWithReflection(p));  
  92.         }  
  93.         timer.Stop();  
  94.         timeElapsedR = timer.Duration;  
  95.    
  96.         Console.WriteLine();  
  97.         Console.ForegroundColor = ConsoleColor.Green;  
  98.         Console.WriteLine("----------------------------------------");  
  99.         Console.WriteLine("Object count:\t\t{0}", count);  
  100.         Console.WriteLine("Cloning Normal:\t\t{0:00.0000} s", timeElapsedN);  
  101.         Console.WriteLine("Cloning IL:\t\t{0:00.0000} s", timeElapsedIL);  
  102.         Console.WriteLine("Cloning Reflection:\t{0:00.0000} s", timeElapsedR);  
  103.         Console.WriteLine("----------------------------------------");  
  104.         Console.ResetColor();  
  105.     }  
  106.    
  107.     ///  
  108.    
  109. <summary>  
  110.     /// Create a list of persons with random data and a given number of items.  
  111.     /// </summary>  
  112.    
  113.    
  114.     /// <param name="count">Number of persons to generate</param>  
  115.     /// <returns>List of generated persons</returns>  
  116.     private static List<Person> CreatePersonsList(int count)  
  117.     {  
  118.         Random r = new Random(Environment.TickCount);  
  119.         List<Person> persons = new List<Person>(count);  
  120.         for (int i = 0; i < count; i++)  
  121.         {  
  122.             Person p = new Person();  
  123.             p.ID = r.Next();  
  124.             p.Name = string.Concat("Slaets_", r.Next());  
  125.             p.FirstName = string.Concat("Filip_", r.Next());  
  126.             persons.Add(p);  
  127.         }  
  128.         return persons;  
  129.     }  
  130.    
  131.     ///  
  132.    
  133. <summary>  
  134.     /// Clone one person object with reflection  
  135.     /// </summary>  
  136.    
  137.    
  138.     /// <param name="p">Person to clone</param>  
  139.     /// <returns>Cloned person</returns>  
  140.     private static Person CloneObjectWithReflection(Person p)  
  141.     {  
  142.         // Get all the fields of the type, also the privates.  
  143.         FieldInfo[] fis = p.GetType().GetFields(System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.NonPublic);  
  144.         // Create a new person object  
  145.         Person newPerson = new Person();  
  146.         // Loop through all the fields and copy the information from the parameter class  
  147.         // to the newPerson class.  
  148.         foreach (FieldInfo fi in fis)  
  149.         {  
  150.             fi.SetValue(newPerson, fi.GetValue(p));  
  151.         }  
  152.         // Return the cloned object.  
  153.         return newPerson;  
  154.     }  
  155.    
  156.     ///  
  157.    
  158. <summary>  
  159.     /// Generic cloning method that clones an object using IL.  
  160.     /// Only the first call of a certain type will hold back performance.  
  161.     /// After the first call, the compiled IL is executed.  
  162.     /// </summary>  
  163.    
  164.    
  165.     /// <typeparam name="T">Type of object to clone</typeparam>  
  166.     /// <param name="myObject">Object to clone</param>  
  167.     /// <returns>Cloned object</returns>  
  168.     private static T CloneObjectWithIL<T>(T myObject)  
  169.     {  
  170.         Delegate myExec = null;  
  171.         if (!_cachedIL.TryGetValue(typeof(T), out myExec))  
  172.         {  
  173.             // Create ILGenerator  
  174.             DynamicMethod dymMethod = new DynamicMethod("DoClone"typeof(T), new Type[] { typeof(T) }, true);  
  175.             ConstructorInfo cInfo = myObject.GetType().GetConstructor(new Type[] { });  
  176.    
  177.             ILGenerator generator = dymMethod.GetILGenerator();  
  178.    
  179.             LocalBuilder lbf = generator.DeclareLocal(typeof(T));  
  180.             //lbf.SetLocalSymInfo("_temp");  
  181.    
  182.             generator.Emit(OpCodes.Newobj, cInfo);  
  183.             generator.Emit(OpCodes.Stloc_0);  
  184.             foreach (FieldInfo field in myObject.GetType().GetFields(System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.NonPublic))  
  185.             {  
  186.                 // Load the new object on the eval stack... (currently 1 item on eval stack)  
  187.                 generator.Emit(OpCodes.Ldloc_0);  
  188.                 // Load initial object (parameter)          (currently 2 items on eval stack)  
  189.                 generator.Emit(OpCodes.Ldarg_0);  
  190.                 // Replace value by field value             (still currently 2 items on eval stack)  
  191.                 generator.Emit(OpCodes.Ldfld, field);  
  192.                 // Store the value of the top on the eval stack into the object underneath that value on the value stack.  
  193.                 //  (0 items on eval stack)  
  194.                 generator.Emit(OpCodes.Stfld, field);  
  195.             }  
  196.                
  197.             // Load new constructed obj on eval stack -> 1 item on stack  
  198.             generator.Emit(OpCodes.Ldloc_0);  
  199.             // Return constructed object.   --> 0 items on stack  
  200.             generator.Emit(OpCodes.Ret);  
  201.    
  202.             myExec = dymMethod.CreateDelegate(typeof(Func<T, T>));  
  203.             _cachedIL.Add(typeof(T), myExec);  
  204.         }  
  205.         return ((Func<T, T>)myExec)(myObject);  
  206.     }  
  207.    
  208.     ///  
  209.    
  210. <summary>  
  211.     /// Clone a person object by manually typing the copy statements.  
  212.     /// </summary>  
  213.    
  214.    
  215.     /// <param name="p">Object to clone</param>  
  216.     /// <returns>Cloned object</returns>  
  217.     private static Person CloneNormal(Person p)  
  218.     {  
  219.         Person newPerson = new Person();  
  220.         newPerson.ID = p.ID;  
  221.         newPerson.Name = p.Name;  
  222.         newPerson.FirstName = p.FirstName;  
  223.         return newPerson;  
  224.     }  
  225. }  

Clone with Extension Methods

I found this blog and it’s great. I am providing the link here.

P.S.

There is nothing much new in this article here asI already found similar writing online. I hope this article enlarges the scope of its original article .This article I will keep for my personal knowledge repository

Ebook Download
View all
Learn
View all