C#中物件copy前後比對常見錯誤
有時可能會將一些表單資料封裝成DTO或者來自EF某張表的record entity
剛好又涉及到要寫複製資料功能進行局部欄位資料異動時候
就會時常發生連動到舊物件資料的問題
有問題寫法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | using System; class Person { public string Name { get; set; } public int Age { get; set; } } public class Program { public static void Main() { Person person1 = new Person(); person1.Age=23; person1.Name="Amy"; Console.WriteLine(String.Format("person1 name:{0} / Age:{1}",person1.Name,person1.Age)); Person person2 = person1; person2.Name = "Ted"; Console.WriteLine(String.Format("person1 name:{0} / Age:{1}",person1.Name,person1.Age)); Console.WriteLine(String.Format("person2 name:{0} / Age:{1}",person2.Name,person2.Age)); Console.ReadLine(); } } |
會觀察到物件複製寫法不對只有異動person2的Name也連動到person1的Name
第一種修正法.重新new並指定欄位
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | using System; class Person { public string Name { get; set; } public int Age { get; set; } } public class Program { public static void Main() { Person person1 = new Person(); person1.Age=23; person1.Name="Amy"; Console.WriteLine(String.Format("person1 name:{0} / Age:{1}",person1.Name,person1.Age)); //Person person2 = person1; //第一種. Person person2 = new Person(){Name=person1.Name,Age=person1.Age}; person2.Name = "Ted"; Console.WriteLine(String.Format("person1 name:{0} / Age:{1}",person1.Name,person1.Age)); Console.WriteLine(String.Format("person2 name:{0} / Age:{1}",person2.Name,person2.Age)); Console.ReadLine(); } } |
第二種修正法.透過反射
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 | using System; using System.Reflection; class Person { public string Name { get; set; } public int Age { get; set; } } public class Program { public static void Main() { Person person1 = new Person(); person1.Age=23; person1.Name="Amy"; Console.WriteLine(String.Format("person1 name:{0} / Age:{1}",person1.Name,person1.Age)); //Person person2 = person1; //第一種. //Person person2 = new Person(){Name=person1.Name,Age=person1.Age}; Type myType = person1.GetType(); Person person2 = (Person)System.Activator.CreateInstance(myType); PropertyInfo[] properties = myType.GetProperties(); foreach (var property in properties) { if (property.CanWrite) { property.SetValue(person2, person1.GetType().GetProperty(property.Name).GetValue(person1, null), null); } } person2.Name = "Ted"; Console.WriteLine(String.Format("person1 name:{0} / Age:{1}",person1.Name,person1.Age)); Console.WriteLine(String.Format("person2 name:{0} / Age:{1}",person2.Name,person2.Age)); Console.ReadLine(); } } |
更省code寫法就是包成extension method
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | using System; using System.Collections.Generic; using System.Reflection; using System.Text; namespace Common.CustomExtension { public static class DeepCopyExtension { public static T GetDeepCopy<T>(this T value) { Type myType = value.GetType(); T copyObj = (T)System.Activator.CreateInstance(myType); PropertyInfo[] properties = myType.GetProperties(); foreach (var property in properties) { if (property.CanWrite) { property.SetValue(copyObj, value.GetType().GetProperty(property.Name).GetValue(value, null), null); } } return copyObj; } } } |
之後只要使用.GetDeepCopy()就可了
Person person2 = person1.GetDeepCopy();
person2.Name = "Ted";
留言
張貼留言