October 29, 2010

使用AutoMapper簡化Data Transfer Object與Business Entity的對應程式碼

在一個layered system中,我們常會使用Data Transfer Object (DTO)在layer與layer間傳遞資料,如Presentation Layer (PL)與Business Logic Layer (BLL)。至於什麼是DTO,可參考筆者另一篇文章Data Transfer Object使用心得及時機,在此也列出Martin Fowler在其書"Patterns of Enterprise Application Architecture"中對DTO的定義,有與趣的朋友可以去google一下或翻一下這本書(在Chapter 15)
An object that carries data between processes in order to reduce the number of method calls.
由於資料傳遞透過DTO,我們將會遇到兩種需要做資料對應的情況
  1. DTO由PL傳遞至Service Layer (SL),於SL將DTO對應至Business Entity後,再把Business Entity送至Data Access Layer (DAL)處理
  2. 資料由DAL取出給BLL後,於SL將Business Entity對應至DTO後回傳至PL
基於以上兩種情況,我們常會看到類似下列的程式碼 (第二種資料對應類型)
UserInfo user = GetUserInfoFromRepository("pete");
UserInfoDto dto = new UserInfoDto();
dto.UserId = user.UserId;
dto.UserAccount = user.UserAccount;
dto.UserPassword = user.UserPassword;
dto.Role = user.Role;
dto.UserName = user.UserName;
return dto;
偏偏這種資料對應不會只存在於一個頁面中,相同的程式碼要copy/paste不僅累人,萬一要是眼花少copy到一行系統不能work搞不好還得debug半天

如果說有個工具或元件能幫我們做這檔事不是樂得輕鬆嗎? 在此推薦一個好用元件AutoMapper
有了它,在最理想的情況下只要一行程式碼(好吧,外加一行建立Mapper物件的程式碼) 就可以輕輕鬆鬆達到DTO與Business Entity的對應
以下為一簡單的範例程式碼
Mapper.CreateMap<UserInfo, UserInfoDto>()
UserInfoDto dto = Mapper.Map<UserInfo, UserInfoDto>(GetUserInfoFromRepository("pete"));
據官方說法,重覆的對應,其Mapper.CreateMap只要宣告一次就可以了,並建議在把它放在Global.asax裡在應用程式啟動時就建立Mapping。當然它還有很多更進階的用法以及資料對應時會產生的一些問題,筆者在此就不多做說明了。