天天看點

C#進階系列——DDD領域驅動設計初探(五):AutoMapper使用

前言:前篇搭建了下WCF的代碼,就提到了DTO的概念,對于為什麼要有這麼一個DTO的對象,上章可能對于這點不太詳盡,在此不厭其煩再來提提它的作用:

從安全上面考慮,領域Model都帶有領域業務,讓Client端引用Domain Model就意味着Client端可以繞過應用層直接完成業務邏輯的調用,這樣是一種不安全的機制。

從對象傳遞效率上面考慮,領域Model帶有業務,而這些業務一般對于UI層是沒有意義的,是以帶有業務的model傳遞起來會加重網絡負擔。

網上還說了DTOmodel最大的意義在于跨平台,Domain Model都是與特定的語言的資料類型有關,而這些資料類型是不能跨平台的,比如Java的類型就不能被C#使用。但在分布式模式下,Client端與Server端的平台不同是很正常的,如果Service直接傳回Domain Model,Client端根本無法解析,這就要求Service傳回的結果必須是标準的格式位元組流。讓Domain Model隻使用簡單類型(字元和數值)?讓資料類型限制Domain Model顯然不是一個好想法,是以DTO似乎是必不可少的了。

既然我們要使用DTO,那麼有一件事我們就非做不可了,我們從領域層得到的是領域Model,如何把領域Model轉換成隻帶有資料屬性的DTO傳遞到前台呢?又或者我們從前台送出一個DTO對象,如何将DTO轉換成領域Model而送出到背景呢?這個時候就需要我們的對象映射工具,目前市面上對象映射工具較多,但部落客最熟悉的還是Automapper,這章就來分享下Automapper的使用。

DDD領域驅動設計初探系列文章:

<a href="http://www.cnblogs.com/landeanfen/p/4816706.html">C#進階系列——DDD領域驅動設計初探(一):聚合</a>

<a href="http://www.cnblogs.com/landeanfen/p/4834730.html">C#進階系列——DDD領域驅動設計初探(二):倉儲Repository(上)</a>

<a href="http://www.cnblogs.com/landeanfen/p/4837520.html">C#進階系列——DDD領域驅動設計初探(三):倉儲Repository(下)</a>

<a href="http://www.cnblogs.com/landeanfen/p/4841211.html">C#進階系列——DDD領域驅動設計初探(四):WCF搭建</a>

<a href="http://www.cnblogs.com/landeanfen/p/4842015.html">C#進階系列——DDD領域驅動設計初探(五):AutoMapper使用</a>

<a href="http://www.cnblogs.com/landeanfen/p/4844344.html" target="_blank">C#進階系列——DDD領域驅動設計初探(六):領域服務</a>

<a href="http://www.cnblogs.com/landeanfen/p/4920577.html" target="_blank">C#進階系列——DDD領域驅動設計初探(七):Web層的搭建</a>

Automapper是一個object-object mapping(對象映射)工具,一般主要用于兩個對象之間資料映射和交換。當然你也可以自己通過反射去寫對象的映射,對于簡單的兩個屬性間的資料轉換,肯定沒什麼問題。但是如果遇到某些複雜的資料轉換,比如指定某一個對象的某個屬性映射到另一個對象的某一個屬性,這種情況如果我們自己手動映射,恐怕就有點麻煩了吧。既然我們有現成的工具,為什麼不用呢?

向項目中添加AutoMapper的引用有兩種方式:

在需要使用AutoMapper的項目檔案上面右鍵→管理Nuget程式包,打開Nuget界面,搜尋Automapper,然後安裝第一個即可。如下圖:

C#進階系列——DDD領域驅動設計初探(五):AutoMapper使用

點選Visual Studio的工具菜單→程式包管理控制台,然後選擇需要安裝Automapper的項目(下圖中的預設項目),最後在控制台裡面輸入指令“Install-Package AutoMapper”指令即可按照Automapper包:

C#進階系列——DDD領域驅動設計初探(五):AutoMapper使用

AutoMapper使用起來還是比較簡單的,最簡單的用法你隻需要兩句話:

首先建立映射,然後傳入需要映射的對象執行映射。相信在項目中使用過AutoMapper的原因肯定也寫過類似這樣的AutoMapperHelper 

C#進階系列——DDD領域驅動設計初探(五):AutoMapper使用
C#進階系列——DDD領域驅動設計初探(五):AutoMapper使用

當然,這是最簡單的用法,稍微複雜點的用法我們在後面慢慢介紹。

前面說了,對于指定某一個對象的某個屬性映射到另一個對象的某一個屬性,這種場景,我們先來看看下面代碼: 

C#進階系列——DDD領域驅動設計初探(五):AutoMapper使用
C#進階系列——DDD領域驅動設計初探(五):AutoMapper使用

 領域層有這兩個實體model,然後我們需要得到下面的DTO_TB_USERS這一個對象

C#進階系列——DDD領域驅動設計初探(五):AutoMapper使用
C#進階系列——DDD領域驅動設計初探(五):AutoMapper使用

 這個時候DTO_TB_USERS這個對象的屬性分布在其他兩個領域實體裡面,我們看看AutoMapper如何解決:

通過上面的代碼,ForMember()方法會指定哪個字段轉換為哪個字段,這樣就完美的将對象的層級結構由二級變成了一級(即将TB_USERS下面TB_DEPARTMENT對象的NAME值轉換成了DTO_TB_USERS的DEPARTMENT_NAME值)。除此之外,Automapper裡面還可以通過ForMember幫我們做其他很多我們想不到的事情,比如可以設定某個屬性值保留初始值,隻需要通過

這一句就幫我們搞定。 

還記得我們在倉儲裡面封裝了傳遞lamada表達式的查詢方法麼?試想,如果我們在Web層裡面也希望傳遞lamada表達式去背景查詢,那麼這個時候就有點問題了,因為我們Web裡面隻能通路DTO的Model,是以隻能傳入DTO Model的lamada,而我們倉儲裡面需要傳入的是領域Model的lamada,那麼問題就來了,這兩個lamada表達式之間必須存在一個轉換關系,試想,這些東西如果讓我們手動去處理,還是有難度的吧!還好,我們神奇的Automapper替我們想到了。它能夠幫我們将DTO的lamada轉換成領域Model的lamada,來看看代碼吧:

C#進階系列——DDD領域驅動設計初探(五):AutoMapper使用
C#進階系列——DDD領域驅動設計初探(五):AutoMapper使用

上面方法完美實作了兩種lamada之間的轉換,但根據部落客的使用經曆,這種轉換對屬性的類型有很嚴格的要求,必須保證領域model和DTO的Model同一個屬性的類型完全相同,否則容易報異常。使用的時候需要注意。實際使用的方法:

C#進階系列——DDD領域驅動設計初探(五):AutoMapper使用
C#進階系列——DDD領域驅動設計初探(五):AutoMapper使用

調用

C#進階系列——DDD領域驅動設計初探(五):AutoMapper使用
C#進階系列——DDD領域驅動設計初探(五):AutoMapper使用

除了上面介紹的Automapper的幾個簡單使用,其他還有其他的一些用法。

網上很多介紹DataReader對象和實體類之間的映射:

C#進階系列——DDD領域驅動設計初探(五):AutoMapper使用
C#進階系列——DDD領域驅動設計初探(五):AutoMapper使用

本文轉自懶得安分部落格園部落格,原文連結:http://www.cnblogs.com/landeanfen/p/4842015.html,如需轉載請自行聯系原作者