AutoMapper目錄:
【AutoMapper官方文檔】DTO與Domin Model互相轉換(上)
【AutoMapper官方文檔】DTO與Domin Model互相轉換(中)
【AutoMapper官方文檔】DTO與Domin Model互相轉換(下)
未完待續。。。
本篇目錄:
Mapping Inheritance-映射繼承
Queryable Extensions (LINQ)-擴充查詢表達式
Configuration-配置
Conditional Mapping-條件映射
AutoMapper版本變化點
類型映射優先級
後記
關于AutoMapper寫到這基本的東西都差不多了,上一篇定義為靈活配置篇,本篇可以定義為擴充應用篇,加一些補充,關于AutoMapper的項目應用,網上找了幾篇英文文章,雖然看不懂,但是代碼是相通的,感覺很不錯,主要是EntityFramework中運用AutoMapper,資料通路中使用AutoMapper,有支援的,也有反對的,也有提出建議的,自己也正在摸索,希望有機會寫篇文章和大家分享下。
插一句:寫這些東西,看的人真的很少,還不如像前幾天大家寫篇水文,來讨論下C#的好壞增加點人氣,呵呵,但是如果是這種思想來程式設計真是不可饒恕,寫這種文章的目的不一定是分享給别人,也是對自己學習的另一種修煉,畢竟肚子沒有什麼東西,是寫不出來,也是在逼迫自己去學習,當去學習一點東西後,發現其實并不像想象的那麼簡單,還有很多的東西要去學習,恨隻恨自己晚生了幾年,還需努力。
關于映射繼承,其實在“Lists and Array-集合和數組”這一節點有提到,但是隻是說明下AutoMapper解決映射繼承所使用的方式,這邊我們說下關于AutoMapper在映射繼承中的一些特性,比如下面轉換示例:
源對象和目标對象存在繼承關系,和“Lists and Array”節點裡面的的示例一樣,我們首先要配置AutoMapper,添加類型映射關系和依賴關系,如下:
關于這三段代碼的意義,在“Lists and Array”節點中也有說明,如果我們注釋掉第一段代碼,我們在做派生類映射轉換的時候就會報錯,如果我們把下面兩段代碼去掉,我們在做派生類映射轉換的時候就會映射到基類,說明第一段代碼的意義是,不僅僅包含Order到OrderDto之間的類型映射,還包含Order與OrderDto所有派生類之間的映射,但是隻是聲明,如果要對派生類之間進行類型映射轉換,就還得需要建立派生類之間的類型映射關系。
我們在“Lists and Array”節點中這樣執行類型映射轉換:
上面這段轉換代碼是指定了源泛型類型(Source)和目标泛型類型類型(Dest),是以AutoMapper會根據指定的類型就可以進行轉換了,前提是類型映射關系配置正确,要不然就會報“AutoMapperConfigurationException”異常。如果我們不指定目标資料類型,然後就行轉換會怎樣呢?比如下面轉換:
轉換效果:

代碼中我們并沒有指定目标資料類型,隻是指定一個派生類的基類,如果按照我們的了解,這段代碼執行的結果應該是:轉換結果mapped對象的類型應該是OrderDto類型,但是确是我們希望想要的OnlineOrderDto類型,雖然我們沒有指定目标類型為OnlineOrderDto,但是這一切AutoMapper都幫你做了,就是說AutoMapper會自動判斷目标類型與源資料類型存在的關系,并找出最合适的派生類類型。
注:關于Entity Framework中資料類型映射正在研究,網上找了很多英文文章,還在消化中,這一節點隻是簡單的說下AutoMapper查詢表達式的用法,過幾天再整理一篇關于實體架構中運用資料類型映射的文章,功力不夠,還請包涵。
當我們使用Entity Framework與AutoMapper結合進行查詢對象轉換的時候,使用Mapper.Map方法,就會發現查詢結果對象中的所有屬性和目标屬性對象屬性都會轉換,當然你也可以在查詢結果集中建構一個所需結果的示例,但是這樣做并不是可取的,AutoMapper的作者擴充了QueryableExtensions,使得我們在查詢的時候就可以實作轉換,比如下面示例:
代碼中的.Project().To就是擴充的查詢表達式,詳細表達式代碼:
View Code
我們在前幾節點中說的自定義映射規則,其實也是屬于查詢表達式的一種,結合實體架構可以簡單的應用下,比如我們要映射到DTO中一個Count屬性,來計算查詢結果集中的數量,如下面代碼:
LINQ支援聚合查詢,AutoMapper支援LINQ的擴充方法。在自定義映射中,如果我們講屬性名稱TotalContacts改為ContactsCount,AutoMapper将自動比對到COUNT()擴充方法和LINQ提供程式将轉化計數到相關子查詢彙總子記錄。AutoMapper還可以支援複雜的聚合和嵌套的限制,如果LINQ提供的表達式支援它,例如下面代碼:
上面計算的是每門課程,學生名字開頭為“A”的學生數量。
不是所有的映射選項都支援表達式,因為它必須有LINQ的支援,支援的有:
MapFrom
Ignore
不支援的有:
Condition
DoNotUseDestinationValue
SetMappingOrder
UseDestinationValue
UseValue
ResolveUsing
Any calculated property on your domain object
AutoMapper提供了個性化設定Profile,使得我們轉換後的資料格式可以多變,當然還可以配置全局格式等等,需要繼承自Profile,并重寫Configure方法,然後在AutoMapper初始化的時候,講自定義配置添加到映射配置中,如下面示例:
先建立了一個MoneyFormatter字元格式化類,然後建立ViewModelProfile配置類,在Configure方法中,添加類型映射關系,ForSourceType指的是講中繼資料類型添加格式化,配置使用代碼:
可以看到在Mapper.Initialize初始化的時候,把ViewModelProfile添加到AutoMapper配置中,泛型類型參數必須是Profile的派生類,因為我們在ViewModelProfile的Configure方法中添加了Order到OrderListViewModel類型映射關系,是以我們再初始化的時候就不需要添加了,轉換效果:
在“Flattening-複雜到簡單”節點中,我們說到AutoMapper映射轉換遵循PascalCase(帕斯卡命名規則),是以我們在類型名稱命名要按照PascalCase進行命名,除了預設的命名規則,AutoMapper還提供了一種命名規則,如下:
SourceMemberNamingConvention表示源資料類型命名規則,DestinationMemberNamingConvention表示目标資料類型命名規則,LowerUnderscoreNamingConvention和PascalCaseNamingConvention是AutoMapper提供的兩個命名規則,前者命名是小寫并包含下劃線,後者就是帕斯卡命名規則,是以映射轉換的效果是:property_name -> PropertyName。
當然除了在AutoMapper初始化的時候配置命名規則,也可以在Profile中添加全局配置,如下:
AutoMapper允許在類型映射之前添加條件,例如下面示例:
上面示例表示當源資料baz大于0的時候,才能執行映射,關鍵字是Condition,Condition方法接受一個Func<TSource, bool>類型參數,注意已經指定傳回值為bool類型,方法簽名:
在AutoMapper1.1版本中,如果我們要對類型嵌套映射中加入自定義類型映射,比如下面示例:
可以看出,我們需要在每個類型映射的地方要加:.ForMember(o=>o.Id, m=>m.MapFrom(s=>s.OrderId));但是Order、OnlineOrder和MailOrder存在繼承關系,難道我們如果再加一個派生類映射,就得加一段這樣代碼,這樣就會代碼就會變得難以維護。在AutoMapper2.0版本中解決了這一問題,隻需要下面這樣配置就可以了:
Explicit Mapping (using .MapFrom())-顯式映射:優先級最高,我們使用MapFrom方法定義映射規則,比如:.ForMember(dest => dest.EventDate, opt => opt.MapFrom(src => src.EventDate.Date))
Inherited Explicit Mapping-繼承的顯式映射:就是存在繼承關系的MapFrom定義映射規則映射。
Ignore Property Mapping-忽略屬性映射:使用Ignore方法指定屬性忽略映射,比如:Mapper.CreateMap<Source, Destination>().ForMember(dest => dest.SomeValuefff, opt => opt.Ignore());
Convention Mapping (Properties that are matched via convention)-公約映射:公約映射即符合PascalCase命名規則的映射。如Source類中有Value屬性,Dest類中也有Value屬性,Source和Dest映射關系即是公約映射。
Inherited Ignore Property Mapping-繼承的忽略屬性映射:優先級最低,就是存在繼承關系的忽略屬性映射。
我們舉個簡單示例來說明下映射優先級:
轉換後mapped對象的Referrer屬性值為“google”,但是你發現我們在配置映射規則的時候,不是把Referrer屬性給Ignore(忽略)了嗎?因為OnlineOrder的ReferrerOrderDto的Referrer屬性符合PascalCase命名規則,即是公約映射,雖然忽略屬性映射的優先級比公約映射高,但是上面示例中Order和OnlineOrder存在繼承關系,即是繼承的忽略屬性映射,是以優先級比公約映射要低。
示例代碼下載下傳:http://pan.baidu.com/s/1comgI
如果你覺得本篇文章對你有所幫助,請點選右下部“推薦”,^_^
參考資料:
https://github.com/AutoMapper/AutoMapper/wiki
http://www.cnblogs.com/dudu/archive/2011/12/16/2284828.html
http://www.cnblogs.com/ego/archive/2009/05/13/1456363.html
http://www.cnblogs.com/jiguixin/archive/2011/09/19/2181521.html
http://blog.csdn.net/yujunwu2525/article/details/7850486
作者:田園裡的蟋蟀
微信公衆号:你好架構
出處:http://www.cnblogs.com/xishuai/
公衆号會不定時的分享有關架構的方方面面,包含并不局限于:Microservices(微服務)、Service Mesh(服務網格)、DDD/TDD、Spring Cloud、Dubbo、Service Fabric、Linkerd、Envoy、Istio、Conduit、Kubernetes、Docker、MacOS/Linux、Java、.NET Core/ASP.NET Core、Redis、RabbitMQ、MongoDB、GitLab、CI/CD(持續內建/持續部署)、DevOps等等。
本文版權歸作者和部落格園共有,歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁面明顯位置給出原文連接配接。
分享到:
QQ空間
新浪微網誌
騰訊微網誌
微信
更多