天天看點

【AutoMapper官方文檔】DTO與Domin Model互相轉換(中)

  automapper目錄:

持續更新中。。。

  本篇目錄:

  随着automapper的學習深入,發現automapper在對象轉換方面(object-object

mapping)還蠻強大的,當時使用automapper的場景是dto與domin

model互相轉換,是以文章的标題就是這個(标題有誤),其實automapper不止在這方面的轉換,應該是涵蓋所有對象(object)之間的轉換,上篇主要講automapper的基本轉換使用,本篇可以定義為automapper的靈活配置篇。

  插一句:有時候學習一門技術,還沒有學很深入,發現還有比其更好的,然後就去學習另外一門技術,可能到頭來什麼也沒學會、學精,前兩天看一篇,其實不是c#不好,而是你沒有學好,就像前幾年讨論c#和java哪個好一樣,我個人覺得去争論這些很是無聊,還不如靜下心,好好的學好一門技術,那就是成功的。

  在上篇中,我們使用automapper類型映射轉換,都是相同的類型轉換,比如string轉string、datetime轉datetime,但是有時候在一些複雜的業務場景中,可能會存在跨類型映射轉換,比如我們下面的場景:

  從代碼中可以看出,string需要轉換為目标類型:int、datetime和type,轉換的類型并不一緻,雖然我們命名符合pascalcase命名規則,但是如果還是按照正常的類型映射轉換就會報下面異常:

【AutoMapper官方文檔】DTO與Domin Model互相轉換(中)

  ”automappermappingexception“這個異常我們在上篇中提到多次,automapper在類型映射的時候,如果找不到或映射類型不一緻都會報這個異常,怎麼辦?天無絕人之路,automapper提供了自定義類型轉換器:

  convertusing是什麼?它是我們在指定類型映射時,類型配置的方法,就是說通過convertusing方法把類型映射中類型轉換的權限交給使用者配置,而不是通過automapper進行自動類型轉換,這就給我提供了更多的自定義性,也就避免了不同類型之間轉換而引起的”automappermappingexception“異常。

  convertusing三個重載方法,第二個适用于簡單類型轉換,接受一個類型,傳回一個目标類型,第一個和第三個其實基本一樣,一個是執行個體,一個是類型,但都必須是itypeconverter<tsource,

tdestination>泛型接口的派生類。

  正好上面示例中需要對三種類型進行轉換,就分别用convertusing三個重載方法,因為string轉int很簡單就使用第二個重載方法,string轉datetime、type自定義類型轉換器:

  當然業務場景如果複雜的話,可以在轉換器中做些詳細的配置内容,typeconverter的canconvertto方法是判斷互相轉換類型的可行性,不可轉換傳回false,除此之外,再列下typeconverter的幾個常用方法:

canconvertfrom(type)

傳回該轉換器是否可以将給定類型的對象轉換為此轉換器的類型。

canconvertfrom(itypedescriptorcontext,

type)

傳回該轉換器是否可以使用指定的上下文将給定類型的對象轉換為此轉換器的類型。

canconvertto(type)

傳回此轉換器是否可将該對象轉換為指定的類型。

canconvertto(itypedescriptorcontext,

傳回此轉換器是否可以使用指定的上下文将該對象轉換為指定的類型。

convertfrom(object)

将給定值轉換為此轉換器的類型。

convertfrom(itypedescriptorcontext,

cultureinfo, object)

使用指定的上下文和區域性資訊将給定的對象轉換為此轉換器的類型。

  automapper配置轉換代碼:

  在自定義轉換配置中雖然配置了轉換類型,但是createmap中也需要制定其類型,而且要和轉換器中類型所一緻,最後mapper.createmap<source,

destination>();完成source到destination的配置轉換,其實上面的配置器可以看成source(原始類型)和destination(目标類型)所依賴類型之間的轉換。轉換效果:

【AutoMapper官方文檔】DTO與Domin Model互相轉換(中)

  自定義轉換配置器的強大之處在于,我們可以完成任何類型之間的互相轉換(隻要符合canconvertto),因為類型轉換我們說了算,在業務場景中,我們可以定義一組自定義轉換配置器,這樣就不需要再做額外的配置,就可以完成想要的類型轉換。

  上面講了自定義類型轉換器,針對的是不同類型之間映射處理,有這樣一種場景:領域模型到dto的轉換,dto并不是和領域模型之間完全一樣,而且還要根據具體的業務場景做一些處理,什麼意思?比如我們要對dto做一些測試或其他一些資料操作(如記錄日志時間等),但是和業務無關,如果把這種操作放在領域模型中就有點不倫不類了,是以要在dto轉換中去做,比如下面場景:

  轉換目标對象中我們想得到一個計算值,就是在轉換中對目标值進行解析,如果你看了這一節點,可能覺得很簡單,我們可以使用自定義轉換規則就可以做到:

  這種方式雖然可以解決上述場景中的問題,但是不提倡這樣做,如果解析過程複雜一些,或者解析方式經常出現改動,這樣我們維護起來就很麻煩了,是以我們要定義一個值解析器,或者稱為目标值解析器,和上面說的類型轉換器(convertusing)比較類似,automapper提供了resolveusing方法用于目标值解析器:

  可以看到resolveusing方法和convertusing方式比較類似,resolveusing方法參數對象必須是抽象類valueresolver<tsource,

tdestination>的派生類,準确的說是接口ivalueresolver的派生類,和自定義轉換器一樣,我們要自定義一個目标值解析器:

  customresolver目标值解析器繼承valueresolver,指定源類型和目标值類型,并重寫resolvecore抽象方法,傳回操作值,automapper配置映射類型轉換:

  轉換效果:

【AutoMapper官方文檔】DTO與Domin Model互相轉換(中)

  除了上述使用方式,automapper還提供了自定義構造方法方式,英文原文:“because

we only supplied the type of the custom resolver to automapper, the mapping

engine will use reflection to create an instance of the value resolver.if we

don‘t want automapper to use reflection to create the instance, we can either

supply the instance directly, or use the constructedby method to supply a custom

constructor method.automapper will execute this callback function instead of

using reflection during the mapping operation, helpful in scenarios where the

resolver might have constructor arguments or need to be constructed by an ioc

container.”

  就像上述這段話的最後,我了解的這種方式适用于自定義解析器中存在構造方法參數,或者通過ioc容器來建構,轉換效果和上面那種方式一樣,調用示例:

  空值替換,顧名思義就是原始值為空,在轉換配置中我們定義替換空值的值,使用nullsubstitute方法,使用方式類似于ignore方法,隻不過ignore是忽略或不包含的意思,nullsubstitute是為空指派,接受一個object類型的參數,就是我們要指定替換的值,使用很簡單,貼下示例代碼:

  第一次轉換源值對象為null,我們指定替換null的值為“other

value”,并列印出目标類型轉換值,第二次轉換源值對象為“not

null”,配置和第一次轉換一樣,并列印出目标類型轉換值。轉換效果:

【AutoMapper官方文檔】DTO與Domin Model互相轉換(中)

  automapper中擴充了關于ioc的應用,這樣使得我們在項目中應用automapper更加靈活多變,但适用于大型項目或者業務場景很複雜的情況下,簡單的項目沒必要這樣做,關于ioc的相關知識可以參照:,automapper提供了ioc應用的相關示例代碼,但是有些錯誤,比如在inversionofcontrol類檔案第81行:

【AutoMapper官方文檔】DTO與Domin Model互相轉換(中)

  應改為:

  運作中還有幾個錯誤,比如ioc配置出錯,automapper配置無效等,都是通過automapper提供相關接口進行注入的,不知道是不是配置問題,以後可以再研究下,這邊稍微整理了下,通過mapper提供的執行個體進行注入,簡單示範下automapper中ioc的應用。

  代碼就這麼多,但是可以簡單展現出automapper中ioc的應用,應用ioc使用的是structuremap,源碼位址:,使用nuget安裝structuremap指令:“install-package

structuremap”,也可以直接添加structuremap.dll,除了structuremap,我們也可以使用微軟提供的unity進行依賴注入,參考教程:。

  上述示例中,我們在ioc中添加了兩個類型映射,iconfiguration對應mapper.configuration(iconfiguration),imappingengine對應mapper.engine(imappingengine),使用addregistry泛型方法在初始化的時候,注入類型映射關系,就像unity中configure加載配置檔案一樣,然後通過objectfactory.getinstance方法解析出注入類型的具體對象,示例中使用automapper預設的configuration和engine執行個體,分别繼承于iconfiguration和imappingengine接口,通過繼承其接口,我們還可以自定義configuration和engine,當然除了iconfiguration和imappingengine接口,automapper還提供了其他的接口類型,比如iconfigurationprovider,iprofileconfiguration,iprofileexpression等等,都可以對其進行ioc管理。

【AutoMapper官方文檔】DTO與Domin Model互相轉換(中)

  示例代碼下載下傳:

  貪多嚼不爛,關于automapper的使用先整理這些,後面會陸續更新,還請關注。

  如果你覺得本篇文章對你有所幫助,請點選右下部“推薦”,^_^

  參考資料: