因為對錶達式樹有點興趣,出於練手的目的,試著寫了一個深拷貝的工具庫。支持.net standard2.0或.net framework4.5及以上。 GitHub地址https://github.com/blurhkh/DeepCopier nuget地址https://www.nuget.org/ ...
因為對錶達式樹有點興趣,出於練手的目的,試著寫了一個深拷貝的工具庫。支持.net standard2.0或.net framework4.5及以上。
GitHub地址https://github.com/blurhkh/DeepCopier
nuget地址https://www.nuget.org/packages/DeepCopier
使用方法如下:
首先創建幾個測試用的類型
public class Author { public string Name { get; set; } } public class Book { public string Title { get; set; } public Author Author { get; set; } public List<string> Tags { get; set; } } public class BookDTO { public string Title { get; set; } public Author Author { get; set; } public List<string> Tags { get; set; } }
Book book = new Book { Author = new Author { Name = "Author" }, Title = "Title", Tags = new List<string> { "dotnet-core", "c#" } }; // 用法1 深拷貝一個對象 Book book2 = Copier.Copy(book); // 或一個IEnumerable<T>的實現類實例(目前僅支持一維數組和ICollection<T>的實現類) HashSet<Book> books = new HashSet<Book>() { book, book }; HashSet<Book> books2 = Copier.Copy(books); // 用法2 新建目標類型實例,並將源對象的屬性值拷貝至目標對象的對應屬性 BookDTO bookDTO = Copier.Copy<Book, BookDTO>(book); // 用法3 將源對象的屬性值拷貝至已存在的目標對象的對應屬性 BookDTO target = new BookDTO(); Copier.Copy(book, target);
同類的工具庫比如較為常見的AutoMapper和一個Reflection.Emit操作IL寫的DeepCopy(https://www.nuget.org/packages/DeepCopy/)
接下來進行一下和他們的性能對比,測試數據採用上面的Book類型,迴圈次數為100萬次。
測試數據如下:
Book book = new Book { Author = new Author { Name = "Author" }, Title = "Title", Tags = new List<string> { "dotnet-core", "c#" } };
測試內容如下(本人PC的CPU為I7 4790k,不同庫的測試代碼分別跑在不同的程式里):
首先和AutoMapper進行對比
BookDTO bookDTO = null; Stopwatch sw = new Stopwatch(); sw.Start(); for (int i = 0; i < 1000000; i++) { bookDTO = DeepCopier.Copier.Copy<Book, BookDTO>(book); } Console.WriteLine($"DeepCopier costed {sw.ElapsedMilliseconds} ms at 1st time."); sw.Restart(); for (int i = 0; i < 1000000; i++) { bookDTO = DeepCopier.Copier.Copy<Book, BookDTO>(book); } // 因為有了前一次的緩存,這裡速度會更快 Console.WriteLine($"DeepCopier costed {sw.ElapsedMilliseconds} ms at 2nd time."); Console.ReadLine();
// AutoMapper需要提前配置 AutoMapper.Mapper.Initialize(config => { config.CreateMap<Book, BookDTO>(); }); BookDTO bookDTO = null; Stopwatch sw = new Stopwatch(); sw.Start(); for (int i = 0; i < 1000000; i++) { bookDTO = AutoMapper.Mapper.Map<Book, BookDTO>(book); } Console.WriteLine($"AutoMapper costed {sw.ElapsedMilliseconds} ms at 1st time."); sw.Restart(); for (int i = 0; i < 1000000; i++) { bookDTO = AutoMapper.Mapper.Map<Book, BookDTO>(book); } Console.WriteLine($"AutoMapper costed {sw.ElapsedMilliseconds} ms at 2nd time."); Console.ReadLine();
// DeepCopy只支持對自身類型的拷貝 Book temp = null; Stopwatch sw = new Stopwatch(); sw.Start(); for (int i = 0; i < 1000000; i++) { temp = DeepCopy.DeepCopier.Copy(book); } Console.WriteLine($"DeepCopy costed {sw.ElapsedMilliseconds} ms at 1st time."); sw.Restart(); for (int i = 0; i < 1000000; i++) { temp = DeepCopy.DeepCopier.Copy(book); } Console.WriteLine($"DeepCopy costed {sw.ElapsedMilliseconds} ms at 2nd time."); Console.ReadLine();