zoukankan      html  css  js  c++  java
  • 使用AutoMapper实现Dto和Model的自由转换(上)

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

    C#代码  收藏代码
    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): 

    C#代码  收藏代码
    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): 

    C#代码  收藏代码
    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): 

    C#代码  收藏代码
    1. public class Publisher  
    2. {  
    3.     public string Name { get; set; }  
    4. }  


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

    C#代码  收藏代码
    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): 

    C#代码  收藏代码
    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: 

    C#代码  收藏代码
    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: 

    C#代码  收藏代码
    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: 

    C#代码  收藏代码
    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之间的数据转换。

  • 相关阅读:
    Oracle的rownum原理和使用
    ehcache 使用笔记
    @PostConstruct 注解
    Dubbo java.io.IOException: Can not lock the registry cache file
    java 学习 todoList
    因为本地没有配置 localhost 导致的 eclipse 的奇葩问题
    cheatsheet——mac 上的一款可以显示软件所有快捷键的小工具
    对象作为 map 的 key 时,需要重写 equals 方法和 hashCode 方法
    eclipse一直报An internal error occurred during: "Building workspace". GC overhead limit exceeded
    如何修改SVN客户端中保存的密码
  • 原文地址:https://www.cnblogs.com/yanglang/p/6911064.html
Copyright © 2011-2022 走看看