最近發現了一個比較有趣的東西 AutoMapper,主要將Model轉換爲DTO,DTO更注重數據,對領域對象進行合理封裝,從而不會將領域對象的行爲過度暴露給表現層。app
先來看一點實例,兩個類之間的映射。ide
首先定義兩個類Source與DTOSource:網站
1 public class Source 2 { 3 public int Id { get; set; } 4 public string Content { get; set; } 5 } 6 7 public class DTOSource 8 { 9 public int Id { get; set; } 10 public string Content { get; set; } 11 }
Source與DTOSource字段徹底相同,來看看它倆如何經過AutoMapper轉換,代碼很簡單。spa
1 Mapper.Initialize(x=>{ 2 x.CreateMap<Source,DTOSource>(); 3 }); 4 5 Source s = new Source{Id=1,Content="123"}; 6 7 DTOSource dto = Mapper.Map<DTOSource>(s);
第一步創建Source到DTOSource之間的映射,初始化一個Source實例後,來看下執行結果:code
執行完成後,能夠看到dto中的數據與以前初始化的s的數據是同樣的,就像是直接將s拷貝了一份給dto,在兩個類字段名定全相同的狀況下如此,那麼若是DTOSource中的字段名與Source中的不相同如何,其實也很簡單,只需對象
要改爲一點點的代碼既可:blog
咱們將DTOSource中的Content的字段名改爲Desc,此時只須要創建映射關係時,指定字段就能夠了:繼承
1 Mapper.Initialize(x => { 2 x.CreateMap<Source, DTOSource>().ForMember(c=>c.Desc,q=> { 3 q.MapFrom(z => z.Content); 4 }); 5 });
來看看運行結果如何;get
能夠看到與以前的運行結果是相同的。string
那麼如何映射兩個List,其實也很簡單,和上述代碼幾乎能夠說是無差異,只是在最後一步時,要作一點點的修改就能夠了。以下面代碼:
1 Mapper.Initialize(x => { 2 x.CreateMap<Source, DTOSource>().ForMember(c => c.Desc, q => 3 { 4 q.MapFrom(z => z.Content); 5 }); 6 }); 7 8 s.Add(new Source { Id = 1, Content = "123" }); 9 10 var dto = Mapper.Map<List<DTOSource>>(s);
能夠看到除了最後一句代碼,其它幾乎是徹底相同的,只是在最後一句代碼中,目標類型改爲了List<DTOSource>僅此而已。看下運行結果如何:
結果符合預期。
在實際的項目中,這樣的寫法確定是不符合要求的,通常會作一個封裝,新建一個SourceProfile繼承自Profile:
1 public SourceProfile() 2 { 3 base.CreateMap<Source, DTOSource>().ForMember(c => c.Desc, q => { 4 q.MapFrom(z => z.Content); 5 }); 6 }
全部映射關係均可以寫在這一個類裏,只須要在程序初始化的時候調用一次就能夠了:
1 Mapper.Initialize(x => { x.AddProfile<SourceProfile>(); });
博主使用的AutoMapper版本6.1.1.0,由於AutoMapper在6.0版本時移除了Profile中的Configure,因此與6.0版本如下寫法有點不一樣,6.0如下版本寫法爲:
1 public class SourceProfile : Profile 2 { 3 protected override void Configure() 4 { 5 CreateMap<Source, DTOSource>().ForMember(c => c.Desc, q => { 6 q.MapFrom(z => z.Content); 7 }); 8 } 9 }
繼承Profile重寫其Configure便可,調用方式與上述沒有太大差異。 Mapper.Initialize中可添加一個或多個Profile。
在MVC項目的應用中,能夠將Mapper.Initialize封裝到一個類裏;
public static class AutoMapperForMvc { public static void Register() { Mapper.Initialize(x => { x.AddProfile<SourceProfile>(); }); } }
進而在MVC的Global中進一次性註冊:
1 public class MvcApplication : System.Web.HttpApplication 2 { 3 protected void Application_Start() 4 { 5 AreaRegistration.RegisterAllAreas(); 6 FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters); 7 RouteConfig.RegisterRoutes(RouteTable.Routes); 8 BundleConfig.RegisterBundles(BundleTable.Bundles); 9 //註冊 10 AutoMapperForMvc.Register(); 11 } 12 }
更多有趣的東西能夠查看官方網站