安裝方式:使用vs自帶的nuget管理工具,搜索automapper ,選擇第一個安裝到你的項目即可。
先說說dto
dto是個什么東東?
dto(data transfer object)就是數據傳輸對象,說白了就是一個對象,只不過里邊全是數據而已。
為什么要用dto?
1、dto更注重數據,對領域對象進行合理封裝,從而不會將領域對象的行為過分暴露給表現層
2、dto是面向ui的需求而設計的,而領域模型是面向業務而設計的。因此dto更適合于和表現層的交互,通過dto我們實現了表現層與領域model之間的解耦,因此改動領域model不會影響ui層
3、dto說白了就是數據而已,不包含任何的業務邏輯,屬于瘦身型的對象,使用時可以根據不同的ui需求進行靈活的運用
我從網上找了一些資料,
automapper
現在我們既然知道了使用dto的好處,那么我們肯定也想馬上使用它,但是這里會牽扯一個問題:怎樣實現dto和領域model之間的轉換?
有兩個思路,我們要么自己寫轉換代碼,要么使用工具。不過就應用而言,我還是覺得用工具比較簡單快捷,那就使用工具吧。其實這樣的轉換工具很多,不過我還是決定使用automapper,因為它足夠輕量級,而且也非常流行,國外的大牛們都使用它。使用automapper可以很方便的實現dto和領域model之間的轉換,它是一個強大的object-object mapping工具。
下載了個demo,然后自己又寫了一遍,我把automapper 的使用分為兩種:
1、viewmodel與實體的字段名字是一致的,viewmodel的字段可以比實體中的字段少,但是不能多。
還有一種情況是:源實體中的字段名字是getxxx,那么viewmodel中對應的字段可以是xxx,也會自動對應賦值,比如我寫的demo中源實體中geta,viewmodel中的a;
再有一種情況就是實體中的實體賦值,在我寫的這個例子中,源實體中包含的實體類字段為sub,里面包含的字段名字為age,
那么destmodel中對應的字段名字可以是:subage,那么automapper就可以自動為你賦值了,大家看最后的運行結果。
給大家看下我建的源實體:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
public class source1 { public string name { set ; get ; } public string geta { set ; get ; } public string getd { set ; get ; } public string setb { set ; get ; } public string c { set ; get ; } public subsource1 sub { set ; get ; } } public class subsource1 { public string age { set ; get ; } } |
還有viewmodel(要轉化成為你想要的模型):
1
2
3
4
5
6
7
8
9
10
11
12
|
public class dest1 { public string name { set ; get ; } public string a { set ; get ; } public string c { set ; get ; } public string subage { set ; get ; } public string d { set ; get ; } } |
我封裝的擴展方法:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
/// <summary> /// 類型映射,默認字段名字一一對應 /// </summary> /// <typeparam name="tdestination">轉化之后的model,可以理解為viewmodel</typeparam> /// <typeparam name="tsource">要被轉化的實體,entity</typeparam> /// <param name="source">可以使用這個擴展方法的類型,任何引用類型</param> /// <returns>轉化之后的實體</returns> public static tdestination mapto<tdestination, tsource>( this tsource source) where tdestination: class where tsource : class { if (source == null ) return default (tdestination); var config = new mapperconfiguration(cfg => cfg.createmap<tdestination, tsource>()); var mapper = config.createmapper(); return mapper.map<tdestination>(source); } |
使用方式:
1
2
3
4
5
6
7
8
9
10
|
var source1 = new source1 { name = "source" , sub = new subsource1 { age = "25" }, c = "c" , geta = "a" , setb = "b" }; var destviewmodel = source1.mapto<dest1, source1>(); |
運行結果:
2.viewmodel與實體字段名字沒有全部對應,只有幾個字段的名字和源實體中的字段名字是一樣的,其他的字段是通過實體中的幾個字段組合或者是格式或者是類型轉化而來的,
使用方法:不能再使用這個擴展方法了,只能自己額外寫代碼,代碼如下:
1
2
3
4
5
6
7
8
9
|
var config2 = new mapperconfiguration( cfg => cfg.createmap<sourceuser, destuser2>() .formember(d => d.destname, opt => opt.mapfrom(s => s.name)) //指定字段一一對應 .formember(d => d.birthday, opt => opt.mapfrom(src => src.birthday.tostring( "yy-mm-dd hh:mm" ))) //指定字段,并轉化指定的格式 .formember(d => d.age, opt => opt.condition(src => src.age > 5)) //條件賦值 .formember(d => d.a1, opt => opt.ignore()) //忽略該字段,不給該字段賦值 .formember(d => d.a1, opt => opt.nullsubstitute( "default value" )) //如果源字段值為空,則賦值為 default value .formember(d => d.a1, opt => opt.mapfrom(src => src.name + src.age * 3 + src.birthday.tostring( "d" )))); //可以自己隨意組合賦值 var mapper2 = config2.createmapper(); |
注釋中都包含了平時常用的幾種情況,其他的我就沒有再寫。
下面再給大家把list轉化的擴展方法代碼貼上:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
/// <summary> /// 集合列表類型映射,默認字段名字一一對應 /// </summary> /// <typeparam name="tdestination">轉化之后的model,可以理解為viewmodel</typeparam> /// <typeparam name="tsource">要被轉化的實體,entity</typeparam> /// <param name="source">可以使用這個擴展方法的類型,任何引用類型</param> /// <returns>轉化之后的實體列表</returns> public static ienumerable<tdestination> maptolist<tdestination, tsource>( this ienumerable<tsource> source) where tdestination : class where tsource : class { if (source == null ) return new list<tdestination>(); var config = new mapperconfiguration(cfg => cfg.createmap<tdestination, tsource>()); var mapper = config.createmapper(); return mapper.map<list<tdestination>>(source); } |
同樣的使用方式:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
var source1 = new source1 { name = "source" , sub = new subsource1 { age = "25" }, c = "c" , geta = "a" , setb = "b" }; var source3 = new source1 { name = "source3" , sub = new subsource1 { age = "253" }, c = "c3" , geta = "a3" , setb = "b3" }; var sourcelist = new list<source1> { source1, source3 }; var destviewmodellist = sourcelist.maptolist<dest1, source1>(); |
運行結果:
以上就是我個人所得,希望對大家的學習有所幫助,也希望大家多多支持服務器之家。
原文鏈接:http://www.cnblogs.com/dawenyang/p/7966850.html