程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> C# >> C#入門知識 >> 使用AutoMapper實現Dto和Model的自由轉換(上)

使用AutoMapper實現Dto和Model的自由轉換(上)

編輯:C#入門知識

在實際的軟件開發項目中,我們的“業務邏輯”常常需要我們對同樣的數據進行各種變換。例如,一個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<Book> Books { get; set; }  
    public Address Address { get; set; }  

    public class BookStore
    {
        public string Name { get; set; }
        public List<Book> Books { get; set; }
        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; }  

    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<Author> Authors { get; set; }  
    public DateTime? PublishDate { get; set; }  
    public Publisher Publisher { get; set; }  
    public int? Paperback { get; set; }  

    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):
C#代碼 
public class Publisher  
{  
    public string Name { get; set; }  

    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; }  

    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; }  

    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<BookDto> Books { get; set; }  
    public AddressDto Address { get; set; }  

    public class BookStoreDto
    {
        public string Name { get; set; }
        public List<BookDto> Books { get; set; }
        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; }  

    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; }  

    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之間的數據轉換。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved