AutoMapper中的Map和DynamicMap——高手注重細節,思考和總結

來源:互聯網
上載者:User

標籤:

近日在做項目的時候,遇到了個怪問題,關於AutoMapper的細節問題,也是不為一般人所關注的。

本人研究AutoMapper也沒有多長時間,而且研究的過程中也寫了關於AutoMapper的系列基礎教程,但是畢竟AutoMapper是個開源項目,並不是一個簡單的系列教程就能解釋的清楚的,只能解釋個大概,項目實戰的時候,遇到的細節問題還得自己私下裡再次研究、總結。

首先,我要說明的是,這篇部落格的寫作順序是按事情發展的順序來寫的,也就是說,在我想寫這篇部落格時,問題的根本原因還沒找到,但是此時,我回過頭來,再來看這個過程中每個問題的解決思路,我想,此時這個細節的問題已經清楚了,也來分享一下。

 

先來讓大家看看我的AutoMapper的大致配置過程:

  • 先建立實體類對應的AutoMapper配置類,命名規範是EntityName(實體類名)+Profile,比如PersonProfile,ProvincePerfile等。
public class ProvinceProfile : Profile{    protected override void Configure()    {        Mapper.Initialize(cfg => cfg.CreateMap<Provinces, ProvinceDto>()            .ForSourceMember(src=>src.UpdatedDate,opt=>opt.Ignore())            .ReverseMap());    }}
  • 再建立一個靜態類,取名AutoMapperConfig,然後在他的靜態方法中初始化Mapper,並添加所有的配置類,這裡我還添加了其他配置類。
public static class AutoMapperWebConfig{    public static void Configure()    {        Mapper.Reset();        Mapper.Initialize(cfg =>        {            cfg.AddProfile<ProvinceProfile>();            cfg.AddProfile<CityProfile>();            cfg.AddProfile<StationProfile>();            cfg.AddProfile<TerminalDeviceProfile>();//TerminalDeviceProfile依賴ProvinceProfile            cfg.AddProfile<OperatorProfile>();          });        Mapper.AssertConfigurationIsValid();//驗證所有的映射配置是否都正常    }}
  • 最後,在項目啟動的時候(ASP.Net程式在.asax檔案中的Application_Start方法)調用AutoMapperWebConfig.Configure();就可以了。

這一切都感覺這麼順利,但是往往越是順利的時候,也意味著不順快來了。接下來,類似下面中的錯誤向我狂轟亂炸。

當我使用在應用程式層使用Mapper.Map()方法將實體類映射為Dto類時,報錯如下:

很明顯這是AutoMapper映射錯誤。

接下來就各種搜尋錯誤,找到了下面一篇部落格,原文

ta的解決方案是,

看到這裡,我很高興,趕緊改了一下自己的代碼,發現果然成功了!但是該博主並沒有給出個所以然來。

但是,我不服氣,我之前已經建立了兩個類之間的映射啊,為啥Mapper.Map()方法不行,我就納悶了,我非得搞清楚這兩者之間的關係不可。

我尋思著,就字面意思來看,一個是“映射”,一個是“動態映射”,會有啥區別呢?

於是各種搜兩者之間的區別,去StackOverflow上找到了下面的答案:原連結

這裡說,DynamicMap在編譯時間你不知道源類型的情況下使用,那麼,相應地,Map就是在編譯時間知道源類型的情況下使用。簡單的這一句解釋並不能讓接觸AutoMapper時間不長的人有所啟示。

而問題就出在,我之前已經建立了映射,所以在編譯時間應該可以確定源類型的,更何況我這兩個類都很簡單,不可能是因為資料類型不一致造成的映射失敗啊!代碼如下:

public class Provinces : Entity{    public virtual string Code{ get; set; }    public virtual string Name{ get; set; }    public virtual string UpdatedBy{ get; set; }    public virtual DateTime? UpdatedDate{ get; set; }    public Provinces(){}}
public class ProvinceDto:EntityDto{    public string Code { get; set; }    public string Name { get; set; }}

 

於是,還得不到自己想要的答案,就去GitHub上AutoMapper的項目下Open了一個Issue,點擊查看我提的Issue,在這裡,我得到了我想要的答案。

該回答者給我的答案如上,他猜想我在每個實體類對應的Profile檔案中,應該直接使用CreateMap,而不是在Mapper.Initialize中使用CreateMap。按照他的提示,我修改了代碼,以後再也沒有出現錯誤。

==================================================該總結了==================================================================

現在再次回頭看看這個問題,完全是瞭然於胸的感覺。因為我在AutoMapperWebconfig靜態類的靜態方法中已經進行了Mapper.Initialize(),這是AutoMapper的初始化,而在每個實體類對應的Profile類中又使用了一次。嘗試著去想一想,第一次將所有的文配置類都初始化到Mapper(暫且先將它理解成一個容器)中,第二次調用Mapper.Initialize()可能會把之前的內容都擦除掉,所以使用Mapper.Map的時候會報錯就可以想明白了,而使用DynamicMap,之前在哪裡看到過DynamicMap就想當於先CreateMap,再Map,所以,我們之前的配置就可有可無,無關緊要了,因為DynamicMap會把之前的配置擦除掉,所以上面中的映射成功了。而至於其他配置類沒有出現該錯誤,該回答者給的答案是”這可能是個意外!“。在這次坎坷曲折的解決問題的過程中,還是學到了很多東西的。在這裡,我們也很顯然,可以看出部落格園那位園友使用DynamicMap成功後而沒給出為什麼,十有八九也是我這個問題了。

==================================================總結完畢==================================================================

AutoMapper中的Map和DynamicMap——高手注重細節,思考和總結

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.