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

來源:互聯網
上載者:User
在實際的軟體開發項目中,我們的“商務邏輯”常常需要我們對同樣的資料進行各種變換。例如,一個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; }

}


書店有自己的地址(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<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; }

}


每本書可以有最多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<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; }

}


以及與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之間的資料轉換。

  • 相關文章

    聯繫我們

    該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

    如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

    A Free Trial That Lets You Build Big!

    Start building with 50+ products and up to 12 months usage for Elastic Compute Service

    • Sales Support

      1 on 1 presale consultation

    • After-Sales Support

      24/7 Technical Support 6 Free Tickets per Quarter Faster Response

    • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.