c# 幾種深拷貝方式的比較
阿新 • • 發佈:2020-12-24
public static class Tools { //利用 BinaryFormatter 實現深拷貝 public static T DeepCopyByBinary<T>(this T obj) { T t = default(T); IFormatter formatter = new BinaryFormatter(); using (MemoryStream ms = new MemoryStream()) { formatter.Serialize(ms, obj); ms.Seek(0, SeekOrigin.Begin); t = (T)formatter.Deserialize(ms); } return t; } //利用 XmlSerializer 實現深拷貝 public static T DeepCopyByXml<T>(this T obj) { T t = default(T); XmlSerializer xmlserialize = new XmlSerializer(typeof(T)); using (MemoryStream ms = new MemoryStream()) { xmlserialize.Serialize(ms, obj); ms.Seek(0, SeekOrigin.Begin); t = (T)xmlserialize.Deserialize(ms); } return t; } //利用反射實現深拷貝 public static T DeepCopyByReflection<T>(this T tSource) { T tResult = Activator.CreateInstance<T>(); Type sourceType = typeof(T); Type resultType = typeof(T); var sourcePros = sourceType.GetProperties(); foreach (var pro in sourcePros) { var sourceProValue = pro.GetValue(tSource); var resultPro = resultType.GetProperty(pro.Name); resultPro.SetValue(tResult, sourceProValue); } return tResult; } }
Person p1 = new Person { Id = 1, Name = "wjire" }; Stopwatch sw1 = new Stopwatch(); sw1.Start(); for (int i = 0; i < 100000; i++) { Person p2 = p1.DeepCopyByBinary(); } sw1.Stop(); Console.WriteLine($"DeepCopyByBinary 共耗時 {sw1.ElapsedMilliseconds} 毫秒"); Stopwatch sw2 = new Stopwatch(); sw2.Start(); for (int i = 0; i < 100000; i++) { Person p2 = p1.DeepCopyByXml(); } sw2.Stop(); Console.WriteLine($"DeepCopyByXml 共耗時 {sw2.ElapsedMilliseconds} 毫秒"); Stopwatch sw3 = new Stopwatch(); sw3.Start(); for (int i = 0; i < 100000; i++) { Person p2 = p1.DeepCopyByReflection(); } sw3.Stop(); Console.WriteLine($"DeepCopyByReflection 共耗時 {sw3.ElapsedMilliseconds} 毫秒"); //利用 json.net 實現深拷貝 Stopwatch sw4 = new Stopwatch(); sw4.Start(); for (int i = 0; i < 100000; i++) { Person p2 = JsonConvert.DeserializeObject<Person>(JsonConvert.SerializeObject(p1)); } sw4.Stop(); Console.WriteLine($"Newtonsoft.Json 共耗時 {sw4.ElapsedMilliseconds} 毫秒");
執行結果:
反射最快!!
class Program { static void Main(string[] args) { Person p1 = new Person(123) { Id = 1, Age = 33, Name = "wjire" }; Expression<Func<Person, Person>> exp1 = p => new Person(333) { Id = p.Id, Name = p.Name, Age = p.Age }; var func1 = exp1.Compile(); Person p23 = func1(p1); Console.WriteLine(p23.Id); Console.WriteLine("*****************************"); ParameterExpression parameterExpression = Expression.Parameter(p1.GetType(), "p"); // 創造了 lambda表示式中的入參: p Console.WriteLine(parameterExpression); List<MemberBinding> memberBindingList = new List<MemberBinding>(); foreach (PropertyInfo pro in p1.GetType().GetProperties()) { if (!pro.CanWrite) { continue; } MemberExpression property = Expression.Property(parameterExpression, pro.Name); Console.WriteLine(property);// p.Id,p.Name,p.Age MemberBinding memberBinding = Expression.Bind(pro, property); Console.WriteLine(memberBinding);// p=p.Id,p=p.Name,p=p.Age memberBindingList.Add(memberBinding); } var rr = Expression.New(p1.GetType().GetConstructor(new Type[] { typeof(int) }), Expression.Constant(default(int))); MemberInitExpression initExpression = Expression.MemberInit(rr, memberBindingList); Console.WriteLine(initExpression);// new Person { Id = p.Id, Name = p.Name, Age = p.Age } Expression<Func<Person, Person>> exp = Expression.Lambda<Func<Person, Person>>(initExpression, parameterExpression); Console.WriteLine(exp);// p => new Person { Id = p.Id, Name = p.Name, Age = p.Age } Func<Person, Person> func = exp.Compile(); Person p2 = func(p1); Console.WriteLine(p2.Name); Console.WriteLine(p2.Id); Console.WriteLine(p2.Age); Console.ReadKey(); } } internal class Person { public int Id { get; set; } public string Name { get; set; } public int Age { get; set; } public Person(int id) { this.Id = id; } }