》,因為內容寫的有點跑偏,關於AutoMapper的使用最後只是簡單寫了下,很明顯這種簡單的使用方式不能滿足項目中復雜的需要,網上找了下AutoMapper相關文檔,但差不多都是像我一樣簡單的概述下,看來懶的不只有我一個,哈哈。在AutoMapper 官方文檔中找到其使用的詳細說明,天書一樣的英文,然後就找相關中文文檔,最後還是沒找到,這邊沒辦法,只能自己動手,豐衣足食了。英語牛逼的可以直接略過,查看英文文檔,本篇也不算是翻譯,因為本人英語實在拿不出手,只是按照示例加上自己的一些理解,做個學習筆記,不對的地方還請指正。
IList<OrderLineItem> _orderLineItems = List<OrderLineItem> Customer Customer { ; AddOrderLineItem(Product product, _orderLineItems.Add( _orderLineItems.Sum(li => Price { ; Name { ; OrderLineItem(Product product, Product = Quantity = Product Product { ; Quantity { ; Quantity * Name { ; CustomerName { ; Total { ; }
customer = Name = order = Customer = bosco = Name = Price = order.AddOrderLineItem(bosco, Mapper.CreateMap<Order, OrderDto> OrderDto dto = Mapper.Map<Order, OrderDto> }
Order和OrderDto之間的類型映射就可以了,我們看OrderDto中的CustomerName和Total屬性在領域模型Order中並沒有與之相對性,沒什麼可以轉換呢,感覺好神奇的樣子,其實仔細發現這些屬性的命名都有一定的規則,AutoMapper在做解析的時候會按照PascalCase(帕斯卡命名法),就是一種變量命名法,除了PascalCase還有Hungarian(匈牙利命名法)和camelCase(駱駝命名法),PascalCase就是指混合使用大小寫字母來構成變量和函數的名字,首字母要大寫,camelCase首字母小寫,我們C#命名中,一般使用的是camelCase和PascalCase,比較高級的是PascalCase。
但是為什麼AutoMapper會解析Total呢?因為在領域模型Order中有個GetTotal()方法,AutoMapper會解析“Get”之後的單詞,所以會與Total相對應,如果你把OrderDto的屬性“Total”改為“Totals”,就會發現得到的“Totals”為0。理解了AutoMapper的解析方式,我們就要注意在編寫變量、屬性或是方法名稱的時候一定要規范,這也是一種好的習慣。
Flattening是由復雜結構簡化,Projection正好相反,投影可以理解為由原始結構千變萬化,我們看下兩種轉換結構:
DateTime EventDate { ; Title { ; DateTime EventDate { ; EventHour { ; EventMinute { ; Title { ; }
calendarEvent = EventDate = DateTime(, , , , , Title = Mapper.CreateMap<CalendarEvent, CalendarEventForm> .ForMember(dest => dest.EventDate, opt => opt.MapFrom(src => src.EventDate.Date)) .ForMember(dest => dest.EventHour, opt => opt.MapFrom(src => src.EventDate.Hour)) .ForMember(dest => dest.EventMinute, opt => opt.MapFrom(src => src.EventDate.Minute)); CalendarEventForm form = Mapper.Map<CalendarEvent, CalendarEventForm> Console.WriteLine(+ Console.WriteLine( + Console.WriteLine( + Console.WriteLine( + }
MapFrom方法中做一些復雜的映射關系操作,MapFrom接受一個lambda表達式作為參數,可以是任何的Func表達式。Projection適用於由簡單到復雜的結構映射,一般體現在業務場景很復雜的情況下。
Projection就是把AutoMapper的映射配置交給用戶來操作】
PascalCase命名法,或者說我們命名是錯誤的,該怎麼辦呢?比如下面代碼:
SomeValue { ; SomeValuefff { ; }
AutoMapper映射:
Mapper.CreateMap<Source, Destination> .ForMember(dest => dest.SomeValuefff, opt => opt.MapFrom(src => src.SomeValue));
AutoMapper提供了Ignore方法,忽略不需要映射的數據結構,我們這樣配置就可以了:
Mapper.CreateMap<Source, Destination> .ForMember(dest => dest.SomeValuefff, opt => opt.Ignore());
sources = Source {Value = Source {Value = Source {Value = Mapper.Initialize(cfg => cfg.CreateMap<Source, Destination> IEnumerable<Destination> ienumerableDest = Mapper.Map<Source[], IEnumerable<Destination>> ICollection<Destination> icollectionDest = Mapper.Map<Source[], ICollection<Destination>> IList<Destination> ilistDest = Mapper.Map<Source[], IList<Destination>> List<Destination> listDest = Mapper.Map<Source[], List<Destination>> Console.WriteLine( + Console.WriteLine( + Console.WriteLine( + Console.WriteLine( + }
來源類型支持上述集合類型,我們可以把來源類型省略掉,因為AutoMapper會自動判斷傳入對象sources的類型,如下:
IEnumerable<Destination> ienumerableDest = Mapper.Map<IEnumerable<Destination>> ICollection<Destination> icollectionDest = Mapper.Map<ICollection<Destination>> IList<Destination> ilistDest = Mapper.Map<IList<Destination>> List<Destination> listDest = Mapper.Map<List<Destination>>(sources);
Value1 { ; Value2 { ; Value1 { ; Value2 { ; }
sources = Mapper.Initialize(cfg => cfg.CreateMap<ParentSource, ParentDestination> .Include<ChildSource, ChildDestination> cfg.CreateMap<ChildSource, ChildDestination> destinations = Mapper.Map<ParentSource[], ParentDestination[]> Console.WriteLine( + destinations[ Console.WriteLine( + destinations[ Console.WriteLine( + destinations[ }
AutoMapperMappingException”異常,但是可以看出AutoMapper並沒有從ChildSource類型映射到ChildDestination類型,而是自動映射到基類型,上面那段映射代碼只是說明派生類和基類之間存在的關系,如果派生類需要映射的話,是需要添加派生類的映射的。
Value { ; InnerSource Inner { ; OtherValue { ; Value { ; InnerDest Inner { ; OtherValue { ; }
source = Value = Inner = InnerSource { OtherValue = Mapper.CreateMap<OuterSource, OuterDest> Mapper.CreateMap<InnerSource, InnerDest> dest = Mapper.Map<OuterSource, OuterDest> Console.WriteLine( + Console.WriteLine( + (dest.Inner == ? : Console.WriteLine( + }
AutoMapperMappingException”異常來判斷類型映射是否正確,因為AssertConfigurationIsValid方法沒有返回值,只能在catch中捕獲了,個人感覺AutoMapper可以提供個bool類型的返回值,驗證成功則返回true。
AutoMapper在配置類型映射最注意的一點是,類型中的名稱一定要按照PascalCase命名規則(Projection和Ignore除外)。