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

热AI工具

Undresser.AI Undress
人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover
用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool
免费脱衣服图片

Clothoff.io
AI脱衣机

AI Hentai Generator
免费生成ai无尽的。

热门文章

热工具

记事本++7.3.1
好用且免费的代码编辑器

SublimeText3汉化版
中文版,非常好用

禅工作室 13.0.1
功能强大的PHP集成开发环境

Dreamweaver CS6
视觉化网页开发工具

SublimeText3 Mac版
神级代码编辑软件(SublimeText3)

热门话题

使用 C# 的 Active Directory 指南。在这里,我们讨论 Active Directory 在 C# 中的介绍和工作原理以及语法和示例。

多线程和异步的区别在于,多线程同时执行多个线程,而异步在不阻塞当前线程的情况下执行操作。多线程用于计算密集型任务,而异步用于用户交互操作。多线程的优势是提高计算性能,异步的优势是不阻塞 UI 线程。选择多线程还是异步取决于任务性质:计算密集型任务使用多线程,与外部资源交互且需要保持 UI 响应的任务使用异步。
