在实际的软件开发项目中,我们的“业务逻辑”常常需要我们对同样的数据进行各种变换。例如,一个Web应用通过前端收集用户的输入成为Dto,然后将Dto转换成领域模型并持久化到数据库中。另一方面,当用户请求数据时,我们又需要做相反的工作:将从数据库中查询出来的领域模型以相反的方式转换成Dto再呈现给用户。有时候我们还会面临更多的数据使用需求,例如有多个数据使用的客户端,每个客户端都有自己对数据结构的不同需求,而这也需要我们进行更多的数据转换。 
频繁的数据转换琐碎而又凌乱,很多时候我们不得不: 
(1)在两个类型几乎只是名字不同而结构大体相似,却只能以手工的、逐个属性赋值的方式实现数据在类型间的“传递”。 
(2)每遇到一个新的数据转换场景就手动实现一套转换逻辑,导致数据转换操作重复而又分散到应用的各个角落。 
如果有这样一个“变形金刚”般的工具,把“橘子”变成我们想要的“苹果”,而我们需要做的只是定义好转换规则——做我们真正的业务逻辑,或者甚至在简单场景下连规则都不需要定义(Convention Over Configuration),那将会是非常美好的事情。事实上在.NET中我们不用重复发明轮子,因为我们有——AutoMapper,一个强大的Object-Object Mapping工具。 
好吧,我承认自己有一点小小的激动,事实上我所做的项目正在经历以上的“困惑”,而AutoMapper确实带给我眼前一亮的感觉。因此我花了一点周末休息时间小小尝试了一把AutoMapper,通过做小的应用场景实现Dto到领域模型的映射,确实感觉到了它的“强大气场”。我将在文章中分享自己的使用心得,希望能给同样处于困惑中的你带来一点帮助。完整的项目代码我会在晚一些时候发布到自己的git repository中,欢迎大家自由参考使用。 
【一】 应用场景说明 
先来看看我所”虚拟“的领域模型。这一次我定义了一个书店(BookStore):

  1. public class BookStore
  2. {
  3. public string Name { get; set; }
  4. public List<Book> Books { get; set; }
  5. public Address Address { get; set; }
  6. }

书店有自己的地址(Address):

  1. public class Address
  2. {
  3. public string Country { get; set; }
  4. public string City { get; set; }
  5. public string Street { get; set; }
  6. public string PostCode { get; set; }
  7. }

同时书店里放了n本书(Book):

  1. public class Book
  2. {
  3. public string Title { get; set; }
  4. public string Description { get; set; }
  5. public string Language { get; set; }
  6. public decimal Price { get; set; }
  7. public List<Author> Authors { get; set; }
  8. public DateTime? PublishDate { get; set; }
  9. public Publisher Publisher { get; set; }
  10. public int? Paperback { get; set; }
  11. }

每本书都有出版商信息(Publisher):

  1. public class Publisher
  2. {
  3. public string Name { get; set; }
  4. }

每本书可以有最多2个作者的信息(Author):

  1. public class Author
  2. {
  3. public string Name { get; set; }
  4. public string Description { get; set; }
  5. public ContactInfo ContactInfo { get; set; }
  6. }

每个作者都有自己的联系方式(ContactInfo):

  1. public class ContactInfo
  2. {
  3. public string Email { get; set; }
  4. public string Blog { get; set; }
  5. public string Twitter { get; set; }
  6. }

差不多就是这样了,一个有着层级结构的领域模型。 
再来看看我们的Dto结构。 
在Dto中我们有与BookStore对应的BookStoreDto:

  1. public class BookStoreDto
  2. {
  3. public string Name { get; set; }
  4. public List<BookDto> Books { get; set; }
  5. public AddressDto Address { get; set; }
  6. }

其中包含与Address对应的AddressDto:

  1. public class AddressDto
  2. {
  3. public string Country { get; set; }
  4. public string City { get; set; }
  5. public string Street { get; set; }
  6. public string PostCode { get; set; }
  7. }

以及与Book相对应的BookDto:

  1. public class BookDto
  2. {
  3. public string Title { get; set; }
  4. public string Description { get; set; }
  5. public string Language { get; set; }
  6. public decimal Price { get; set; }
  7. public DateTime? PublishDate { get; set; }
  8. public string Publisher { get; set; }
  9. public int? Paperback { get; set; }
  10. public string FirstAuthorName { get; set; }
  11. public string FirstAuthorDescription { get; set; }
  12. public string FirstAuthorEmail { get; set; }
  13. public string FirstAuthorBlog { get; set; }
  14. public string FirstAuthorTwitter { get; set; }
  15. public string SecondAuthorName { get; set; }
  16. public string SecondAuthorDescription { get; set; }
  17. public string SecondAuthorEmail { get; set; }
  18. public string SecondAuthorBlog { get; set; }
  19. public string SecondAuthorTwitter { get; set; }
  20. }

注意到我们的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的自由转换(上)的更多相关文章

  1. 使用AutoMapper实现Dto和Model之间自由转换

    应用场景:一个Web应用通过前端收集用户的输入成为Dto,然后将Dto转换成领域模型并持久化到数据库中.另一方面,当用户请求数据时,我们又需要做相反的工作:将从数据库中查询出来的领域模型以相反的方式转 ...

  2. 使用AutoMapper实现Dto和Model的自由转换

    AutoMapper是一个.NET的对象映射工具. 项目地址:https://github.com/AutoMapper/AutoMapper. 帮助文档:https://github.com/Aut ...

  3. 使用AutoMapper实现Dto和Model的自由转换(下)

    书接上文.在上一篇文章中我们讨论了使用AutoMapper实现类型间1-1映射的两种方式——Convention和Configuration,知道了如何进行简单的OO Mapping.在这个系列的最后 ...

  4. 使用AutoMapper实现Dto和Model的自由转换(中)

    在上一篇文章中我们构造出了完整的应用场景,包括我们的Model.Dto以及它们之间的转换规则.下面就可以卷起袖子,开始我们的AutoMapper之旅了. [二]以Convention方式实现零配置的对 ...

  5. AutoMapper完成Dto与Model的转换

    在实际的软件开发项目中,我们的“业务逻辑”常常需要我们对同样的数据进行各种变换. 例如,一个Web应用通过前端收集用户的输入成为Dto,然后将Dto转换成领域模型并持久化到数据库中.相反,当用户请求数 ...

  6. 自制AutoMapper实现DTO到持久层Entity的转换

    自制AutoMapper实现DTO到持久层Entity的转换 项目中经常涉及到页面DTO更新,保存到数据库的操作,这就必然牵扯到DTO和持久层对象的转换,常见的第三方库有: java:dozer .n ...

  7. Swift3.0语言教程字符串与URL的数据转换与自由转换

    Swift3.0语言教程字符串与URL的数据转换与自由转换 Swift3.0语言教程字符串与URL的数据转换 Swift3.0语言教程字符串与URL的数据转换与自由转换,字符串中的字符永久保存除了可以 ...

  8. 【转贴】 Flex 预编译处理 与 手机项目、Web项目、Air项目自由转换

    原文连接: http://bbs.9ria.com/forum.php?mod=viewthread&tid=263350#lastpost 由于这个论坛不稳定,所以转到这里来,这个帖子蛮有用 ...

  9. 简单使用AutoMapper实现DTO转换

    DTO(Data Transfer Object)数据传输对象,只是传输数据,完成与领域对象之间的转换,并不包含领域业务处理. 当领域模型设计人员只关注核心业务,满足于领域模型的精巧,而不关心具体实现 ...

随机推荐

  1. CSS3页面布局方案

    CSS3页面布局方案 Web页面中的布局,在css3之前,主要使用float属性或者position属性进行页面中的简单布局,但是使用它们也存在一些缺点,比如两栏或者多栏中如果元素的内容高度不一致,则 ...

  2. jq插件封装格式

    (function($) { // closure $.fn.hilight = function( options ) { //将方法定义在$的fn上 var defaults = { textCo ...

  3. 修复在“Android 在ScrollView中嵌入ViewPage后ViewPage不能很好的工作的问题解决”这篇博客中MyScrollView出现滑动一会就不会上下滑动的问题

    在“Android 在ScrollView中嵌入ViewPage后ViewPage不能很好的工作的问题解决”,这篇博客中的大部分问题已经解决了. 唯一遗憾的是,ViewPage随人能够工作了,但是My ...

  4. P2962 [USACO09NOV]灯Lights

    贝希和她的闺密们在她们的牛棚中玩游戏.但是天不从人愿,突然,牛棚的电源跳闸了,所有的灯都被关闭了.贝希是一个很胆小的女生,在伸手不见拇指的无尽的黑暗中,她感到惊恐,痛苦与绝望.她希望您能够帮帮她,把所 ...

  5. 50Hz工频干扰消除

    50Hz工频干扰消除 今天整理工频干扰消除算法. 我们知道,设计数字滤波器,和模拟滤波器的实质,其实就是求一组系数,逼近要求的频率响应. 模拟滤波器已经很成熟,因此,数字滤波器的设计,将S平面映射到Z ...

  6. DC-DC Controllers Use Average-Current-Mode Control for Infotainment Applications-3939

    DC-DC Controllers Use Average-Current-Mode Control for Infotainment Applications Abstract: Auto info ...

  7. 使用Highcharts生成折线图_at last

    //数据库数据的读取,读取数据后数据格式的转换,还有highchart数据源的配置,伤透了脑筋. anyway,最终开张了.哈哈! 数据库连接:conn_orcale.php <?php $db ...

  8. 1.4《想成为黑客,不知道这些命令行可不行》(Learn Enough Command Line to Be Dangerous)——编辑命令

    在编辑模式中,命令行包括几个重复之前命令的功能.这些以及其他很多命令功能时常设计键盘上的特殊键,所以给出Table 1作为参考,给出了许多键在典型的Macintosh键盘上的标记符号.若你的键盘不太一 ...

  9. 20155223 Exp3 免杀原理与实践 实验报告

    20155223 Exp3 免杀原理与实践 实验报告 实验前准备 安装Veil-Evasion 直接使用Kali快速安装命令,拒绝采用git安装命令 apt-get -y install veil-e ...

  10. Luogo P2324 [SCOI2005]骑士精神

    所有想练习A*的人都先来敲一下这道题吧. 数据范围即便只有5*5,但朴素的爆搜还是会超时. 因此考虑剪枝. 对于这道题,肯定只要进行最优化剪枝,判断现在走的步数+剩下最少要走的步数,如果大于ans或者 ...