此篇文章用的AutoMapper版本 : 6.2.2 <套件連結>
被同事問到AutoMapper有沒有辦法做泛型的對應,問了一下才發現其他人原來也沒嘗試過這樣的作法,所以來筆記一下供之後參考。
首先對應的Class如下
1 2 3 4 5 6 7 8 9 10 11 12 public class Source <T >{ public int Page1 {get ;set ;} public T Value { get ; set ; } } public class Destination <T >{ public int Page {get ;set ;} public T Value { get ; set ; } }
希望能將Source<T>對應到Destination<T>,而這邊的泛型T有兩組分別如下
1 2 3 4 5 6 7 8 9 10 public class Test { public string Name {get ;set ;} } public class Test1 { public string NickName { get ; set ; } }
同事原本寫的Mapper Configuration對應如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 var config = new MapperConfiguration(cfg => { cfg.CreateMap<Source<Test>, Destination<Test1>>() .ForMember(d => d.Page, o => o.MapFrom(s => s.Page1)) .ForMember(d => d.Value, o => o.MapFrom(s => s.Value)); cfg.CreateMap<Test, Test1>() .ForMember(d => d.NickName, o => o.MapFrom(s => s.name)); }); var mapper = config.CreateMapper(); Source<Test> Source = new Source<Test> { Page = 1 , Value = new Test { name = "hi" } }; Destination<Test1> Result = mapper.Map<Source<Test>, Destination<Test1>>(Source);
這樣寫對應會過,但是變成泛型的T有多種可能時,要寫多組的Source與Destination對應,喪失了AutoMapper的重用性
1 2 3 4 5 6 7 8 9 10 cfg.CreateMap<Source<NewClass2>, Destination<NewClass2>>() .ForMember(d => d.Page, o => o.MapFrom(s => s.Page)) .ForMember(d => d.Value, o => o.MapFrom(s => s.Value)); cfg.CreateMap<Source<NewClass3>, Destination<NewClass4>>() .ForMember(d => d.Page, o => o.MapFrom(s => s.Page)) .ForMember(d => d.Value, o => o.MapFrom(s => s.Value));
能不能讓Source與Destination設定一次就好,之後只要多寫Generic的Type對應即可,其實AutoMapper是有提供的,方式如下
1 2 3 4 cfg.CreateMap(typeof (Source<>), typeof (Destination<>)) .ForMember("Page" ,o => o.MapFrom("Page1" )) .ForMember("Value" ,o => o.MapFrom("Value" ));
之後只要針對泛型的Class補充即可,Source對應到Destination就已經設定完了,以上供參考