使用AutoMapper实现Dto和Model的自由转换(上)
在实际的软件开发项目中,我们的“业务逻辑”常常需要我们对同样的数据进行各种变换。例如,一个Web应用通过前端收集用户的输入成为Dto,然后将Dto转换成领域模型并持久化到数据库中。另一方面,当用户请求数据时,我们又需要做相反的工作:将从数据库中查询出来的领域模型以相反的方式转换成Dto再呈现给用户。有时候我们还会面临更多的数据使用需求,例如有多个数据使用的客户端,每个客户端都有自己对数据结构的不同需求,而这也需要我们进行更多的数据转换。
频繁的数据转换琐碎而又凌乱,很多时候我们不得不:
(1)在两个类型几乎只是名字不同而结构大体相似,却只能以手工的、逐个属性赋值的方式实现数据在类型间的“传递”。
(2)每遇到一个新的数据转换场景就手动实现一套转换逻辑,导致数据转换操作重复而又分散到应用的各个角落。
如果有这样一个“变形金刚”般的工具,把“橘子”变成我们想要的“苹果”,而我们需要做的只是定义好转换规则——做我们真正的业务逻辑,或者甚至在简单场景下连规则都不需要定义(Convention Over Configuration),那将会是非常美好的事情。事实上在.NET中我们不用重复发明轮子,因为我们有——AutoMapper,一个强大的Object-Object Mapping工具。
好吧,我承认自己有一点小小的激动,事实上我所做的项目正在经历以上的“困惑”,而AutoMapper确实带给我眼前一亮的感觉。因此我花了一点周末休息时间小小尝试了一把AutoMapper,通过做小的应用场景实现Dto到领域模型的映射,确实感觉到了它的“强大气场”。我将在文章中分享自己的使用心得,希望能给同样处于困惑中的你带来一点帮助。完整的项目代码我会在晚一些时候发布到自己的git repository中,欢迎大家自由参考使用。
【一】 应用场景说明
先来看看我所”虚拟“的领域模型。这一次我定义了一个书店(BookStore):
- public class BookStore
- {
- public string Name { get; set; }
- public List<Book> Books { get; set; }
- public Address Address { get; set; }
- }
书店有自己的地址(Address):
- public class Address
- {
- public string Country { get; set; }
- public string City { get; set; }
- public string Street { get; set; }
- public string PostCode { get; set; }
- }
同时书店里放了n本书(Book):
- public class Book
- {
- public string Title { get; set; }
- public string Description { get; set; }
- public string Language { get; set; }
- public decimal Price { get; set; }
- public List<Author> Authors { get; set; }
- public DateTime? PublishDate { get; set; }
- public Publisher Publisher { get; set; }
- public int? Paperback { get; set; }
- }
每本书都有出版商信息(Publisher):
- public class Publisher
- {
- public string Name { get; set; }
- }
每本书可以有最多2个作者的信息(Author):
- public class Author
- {
- public string Name { get; set; }
- public string Description { get; set; }
- public ContactInfo ContactInfo { get; set; }
- }
每个作者都有自己的联系方式(ContactInfo):
- public class ContactInfo
- {
- public string Email { get; set; }
- public string Blog { get; set; }
- public string Twitter { get; set; }
- }
差不多就是这样了,一个有着层级结构的领域模型。
再来看看我们的Dto结构。
在Dto中我们有与BookStore对应的BookStoreDto:
- public class BookStoreDto
- {
- public string Name { get; set; }
- public List<BookDto> Books { get; set; }
- public AddressDto Address { get; set; }
- }
其中包含与Address对应的AddressDto:
- public class AddressDto
- {
- public string Country { get; set; }
- public string City { get; set; }
- public string Street { get; set; }
- public string PostCode { get; set; }
- }
以及与Book相对应的BookDto:
- public class BookDto
- {
- public string Title { get; set; }
- public string Description { get; set; }
- public string Language { get; set; }
- public decimal Price { get; set; }
- public DateTime? PublishDate { get; set; }
- public string Publisher { get; set; }
- public int? Paperback { get; set; }
- public string FirstAuthorName { get; set; }
- public string FirstAuthorDescription { get; set; }
- public string FirstAuthorEmail { get; set; }
- public string FirstAuthorBlog { get; set; }
- public string FirstAuthorTwitter { get; set; }
- public string SecondAuthorName { get; set; }
- public string SecondAuthorDescription { get; set; }
- public string SecondAuthorEmail { get; set; }
- public string SecondAuthorBlog { get; set; }
- public string SecondAuthorTwitter { get; set; }
- }
注意到我们的BookDto”拉平了“整个Book的层级结构,一个BookDto里携带了Book及其所有Author、Publisher等所有模式的数据。
正好我们来看一下Dto到Model的映射规则。
(1)BookStoreDto -> BookStore
| BookStoreDto中的字段 | BookStore中的字段 |
| Name | Name |
| Books | Books |
| Address | Address |
(2)AddressDto -> Address
| AddressDto中的字段 | Address中的字段 |
| Country | Country |
| City | City |
| Street | Street |
| PostCode | PostCode |
(3)BookDto -> Book。
BookDto中的一些基本字段可以直接对应到Book中的字段。
| BookDto中的字段 | Book中的字段 |
| Title | Title |
| Description | Description |
| Language | Language |
| Price | Price |
| PublishDate | PublishDate |
| Paperback | Paperback |
每本书至多有2个作者,在BookDto中分别使用”First“前缀和”Second“前缀的字段来表示。因此,所有FirstXXX字段都将映射成Book的Authors中的第1个Author对象,而所有SecondXXX字段则将映射成Authors中的第2个Author对象。
| BookDto中的字段 | Book中的Authors中的第1个Author对象中的字段 |
| FirstAuthorName | Name |
| FirstAuthorDescription | Description |
| FirstAuthorEmail | ContactInfo.Email |
| FirstAuthorBlog | ContactInfo.Blog |
| FirstAuthorTwitter | ContactInfo.Twitter |
注意上表中的ContactInfo.Email表示对应到Author对象的ContactInfo的Email字段,依次类推。类似的我们有:
| BookDto中的字段 | Book中的Authors中的第2个Author对象中的字段 |
| SecondAuthorName | Name |
| SecondAuthorDescription | Description |
| SecondAuthorEmail | ContactInfo.Email |
| SecondAuthorBlog | ContactInfo.Blog |
| SecondAuthorTwitter | ContactInfo.Twitter |
最后还有Publisher字段,它将对应到一个独立的Publisher对象。
| BookDto中的字段 | Publisher中的字段 |
| Publisher | Name |
差不多就是这样了,我们的需求是要实现这一大坨Dto到另一大坨的Model之间的数据转换。
使用AutoMapper实现Dto和Model的自由转换(上)的更多相关文章
- 使用AutoMapper实现Dto和Model之间自由转换
应用场景:一个Web应用通过前端收集用户的输入成为Dto,然后将Dto转换成领域模型并持久化到数据库中.另一方面,当用户请求数据时,我们又需要做相反的工作:将从数据库中查询出来的领域模型以相反的方式转 ...
- 使用AutoMapper实现Dto和Model的自由转换
AutoMapper是一个.NET的对象映射工具. 项目地址:https://github.com/AutoMapper/AutoMapper. 帮助文档:https://github.com/Aut ...
- 使用AutoMapper实现Dto和Model的自由转换(下)
书接上文.在上一篇文章中我们讨论了使用AutoMapper实现类型间1-1映射的两种方式——Convention和Configuration,知道了如何进行简单的OO Mapping.在这个系列的最后 ...
- 使用AutoMapper实现Dto和Model的自由转换(中)
在上一篇文章中我们构造出了完整的应用场景,包括我们的Model.Dto以及它们之间的转换规则.下面就可以卷起袖子,开始我们的AutoMapper之旅了. [二]以Convention方式实现零配置的对 ...
- AutoMapper完成Dto与Model的转换
在实际的软件开发项目中,我们的“业务逻辑”常常需要我们对同样的数据进行各种变换. 例如,一个Web应用通过前端收集用户的输入成为Dto,然后将Dto转换成领域模型并持久化到数据库中.相反,当用户请求数 ...
- 自制AutoMapper实现DTO到持久层Entity的转换
自制AutoMapper实现DTO到持久层Entity的转换 项目中经常涉及到页面DTO更新,保存到数据库的操作,这就必然牵扯到DTO和持久层对象的转换,常见的第三方库有: java:dozer .n ...
- Swift3.0语言教程字符串与URL的数据转换与自由转换
Swift3.0语言教程字符串与URL的数据转换与自由转换 Swift3.0语言教程字符串与URL的数据转换 Swift3.0语言教程字符串与URL的数据转换与自由转换,字符串中的字符永久保存除了可以 ...
- 【转贴】 Flex 预编译处理 与 手机项目、Web项目、Air项目自由转换
原文连接: http://bbs.9ria.com/forum.php?mod=viewthread&tid=263350#lastpost 由于这个论坛不稳定,所以转到这里来,这个帖子蛮有用 ...
- 简单使用AutoMapper实现DTO转换
DTO(Data Transfer Object)数据传输对象,只是传输数据,完成与领域对象之间的转换,并不包含领域业务处理. 当领域模型设计人员只关注核心业务,满足于领域模型的精巧,而不关心具体实现 ...
随机推荐
- PAT B1018 锤子剪刀布 (20 分)
大家应该都会玩“锤子剪刀布”的游戏:两人同时给出手势,胜负规则如图所示: 现给出两人的交锋记录,请统计双方的胜.平.负次数,并且给出双方分别出什么手势的胜算最大. 输入格式: 输入第 1 行给出正整数 ...
- CentOS中配置Kafka集群
环境:三台虚拟机Host0,Host1,Host2 Host0:192.168.10.2 Host1: 192.168.10.3 Host2: 192.168.10.4 在三台虚拟机上配置zook ...
- day47
高级布局 一.文档流(normal flow) 1.概念 本质为normal flow(普通流.常规流)将窗体自上而下分成一行一行,块级元素从上至下.行内元素在每行中从左至右的顺序依次排放元素. v_ ...
- nrf52832 连接参数更新过程
ble 连接参数更新过程如下: 一般分三个过程 一 .主机发起连接(带有一个连接参数,一般都是 7.5ms) 二.主机更新连接参数 (举例:NRF CONNECT 安卓app软件 45ms). 三.从 ...
- 虚拟机上不能使用CUDA
虚拟机的显卡是虚拟的,不能使用CUDA(至少很难),搞了一天才晃过神来: lspci 查找目前主机的硬件配备 用 grep -i 进行大小写无关的搜索
- 【html】前端实现筛选条件跳转
之前与PHP的合作模式之一是前端这边负责写好静态页面交货. 那现在新进的公司,PHP说筛选由前端来实现. 嗯,好吧.实现就实现,多锻炼下咯. <div class="fliter&qu ...
- WPF的Style的TargetType不同写法的异同
原文:WPF的Style的TargetType不同写法的异同 <Style TargetType="TextBlock"> <Setter Property=&q ...
- 探索sklearn | K均值聚类
1 K均值聚类 K均值聚类是一种非监督机器学习算法,只需要输入样本的特征 ,而无需标记. K均值聚类首先需要随机初始化K个聚类中心,然后遍历每一个样本,将样本归类到最近的一个聚类中,一个聚类中样本特征 ...
- Hadoop日记Day9---HDFS的java访问接口
一.搭建Hadoop 开发环境 我们在工作中写完的各种代码是在服务器中运行的,HDFS 的操作代码也不例外.在开发阶段,我们使用windows 下的eclipse 作为开发环境,访问运行在虚拟机中的H ...
- spfa 单源最短路究极算法
学习博客链接:SPFA 求单源最短路的SPFA算法的全称是:Shortest Path Faster Algorithm. SPFA算法是西南交通大学段凡丁于1994年发表的. 从名字我 ...