c#用表达式树实现深拷贝功能
因为对表达式树有点兴趣,出于练手的目的,试着写了一个深拷贝的工具库。支持.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 = ; i < ; i++)
{
bookDTO = AutoMapper.Mapper.Map<Book, BookDTO>(book);
}
Console.WriteLine($"AutoMapper costed {sw.ElapsedMilliseconds} ms at 1st time."); sw.Restart(); for (int i = ; i < ; 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 = ; i < ; i++)
{
temp = DeepCopy.DeepCopier.Copy(book);
}
Console.WriteLine($"DeepCopy costed {sw.ElapsedMilliseconds} ms at 1st time."); sw.Restart(); for (int i = ; i < ; i++)
{
temp = DeepCopy.DeepCopier.Copy(book);
}
Console.WriteLine($"DeepCopy costed {sw.ElapsedMilliseconds} ms at 2nd time.");
Console.ReadLine();

c#用表达式树实现深拷贝功能的更多相关文章
- C#使用表达式树动态调用方法并实现99乘法表
我们在使用C#编程的时候,经常使用反射来动态调用方法,但有时候需要动态的生成方法,下面介绍使用表达式树的方式来自动生成方法,并调用. 首先需要说明什么是表达式,熟悉Linq的程序猿都用过类似于下面的代 ...
- 【C#表达式树 四】Expression类上的函数列表
Expression相当于工厂,这个工厂有各式各样的模型(函数),用来生成各种零部件(节点类型),最后组装成表达式树. Expressions这个命名空间有各种个容器用陈放生产出来的零部件. Expr ...
- C#3.0新增功能10 表达式树 01 简介
连载目录 [已更新最新开发文章,点击查看详细] 如果你使用过 LINQ,则会有丰富库(其中 Func 类型是 API 集的一部分)的经验. (如果尚不熟悉 LINQ,建议阅读 LINQ 教程,以 ...
- C#3.0新增功能10 表达式树 02 说明
连载目录 [已更新最新开发文章,点击查看详细] 表达式树是定义代码的数据结构. 它们基于编译器用于分析代码和生成已编译输出的相同结构.表达式树和 Roslyn API 中用于生成分析器和 Cod ...
- C#3.0新增功能10 表达式树 03 支持表达式树的框架类型
连载目录 [已更新最新开发文章,点击查看详细] 存在可与表达式树配合使用的 .NET Core framework 中的类的大型列表. 可以在 System.Linq.Expressions 查 ...
- C#3.0新增功能10 表达式树 05 解释表达式
连载目录 [已更新最新开发文章,点击查看详细] 表达式树中的每个节点将是派生自 Expression 的类的对象. 该设计使得访问表达式树中的所有节点成为相对直接的递归操作. 常规策略是从根节点 ...
- C#3.0新增功能10 表达式树 06 生成表达式
连载目录 [已更新最新开发文章,点击查看详细] 到目前为止,你所看到的所有表达式树都是由 C# 编译器创建的. 你所要做的是创建一个 lambda 表达式,将其分配给一个类型为 Expressi ...
- C#3.0新增功能10 表达式树 07 翻译(转换)表达式
连载目录 [已更新最新开发文章,点击查看详细] 本篇将介绍如何访问表达式树中的每个节点,同时生成该表达式树的已修改副本. 以下是在两个重要方案中将使用的技巧. 第一种是了解表达式树表示的算法,以 ...
- C#3.0新增功能10 表达式树 04 执行表达式
连载目录 [已更新最新开发文章,点击查看详细] 表达式树 是表示一些代码的数据结构. 它不是已编译且可执行的代码. 如果想要执行由表达式树表示的 .NET 代码,则必须将其转换为可执行的 IL ...
随机推荐
- H264码流中SPS PPS详解<转>
转载地址:https://zhuanlan.zhihu.com/p/27896239 1 SPS和PPS从何处而来? 2 SPS和PPS中的每个参数起什么作用? 3 如何解析SDP中包含的H.264的 ...
- C++Primer笔记-----day03
==============================================================day03================================= ...
- e s6 知识点
http://es6.ruanyifeng.com/#docs/reflect 1.资料对es6箭头函数中的this总结:箭头函数中的this指向的是 定义时的this,而不是 执行时的this.
- Python迭代dict的value
我们已经了解了dict对象本身就是可迭代对象,用 for 循环直接迭代 dict,可以每次拿到dict的一个key. 如果我们希望迭代 dict 对象的value,应该怎么做? dict 对象有一个 ...
- Apache Hive (五)DbVisualizer配置连接hive
转自:https://www.cnblogs.com/qingyunzong/p/8715250.html 一.安装DbVisualizer 下载地址http://www.dbvis.com/ 也可以 ...
- css实现类似heigth:100%的方法
1. 效果 2. 代码 2.1. Html <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" &q ...
- [bzoj2648]SJY摆棋子(带插入kd-tree)
解题关键:带插入kdtree模板题. #include<iostream> #include<cstdio> #include<cstring> #include& ...
- 解剖Nginx·自动脚本篇(5)编译器相关主脚本
在 Nginx 的自动脚本中,auto/cc目录下的所有脚本都是用于编译器相关配置使用的.Nginx的出色跨平台性(Linux.Darwin.Solaris.Win32 等)就有这些脚本的贡献.该目录 ...
- if UNITY_EDITOR这个判断常用,还有哪个常用捏?
#if DEVELOPMENT_BUILD || UNITY_EDITOR DEVELOPMENT_BUILD表示开发版的意思,会在程序右下角显示 Development Build 我们可以根据这个 ...
- copy&mutableCopy 浅拷贝(shallow copy)深拷贝 (deep copy)
写在前面 其实看了这么多,总结一个结论: 拷贝的初衷的目的就是为了:修改原来的对象不能影响到拷贝出来得对象 && 修改拷贝出来的对象也不能影响到原来的对象 所以,如果原来对象就是imm ...