返回總目錄
List和陣列
AutoMapper只要求元素型別的配置而不要求可能會用到的任何陣列或者list型別。比如,我們有一個簡單的源和目標型別:
public class Source { public int Value { get; set; } } public class Destination { public int Value { get; set; } }
支援所有的基本泛型集合,程式碼如下:
class Program { static void Main(string[] args) { Mapper.CreateMap<Source, Destination>(); var sources = new[] { new Source() {Value = 1}, new Source() {Value = 2}, new Source() {Value = 3}, }; IEnumerable<Destination> iEnumerableDests= Mapper.Map<IEnumerable<Destination>>(sources); ICollection<Destination> iCollectionDests= Mapper.Map<ICollection<Destination>>(sources); IList<Destination> iListDests= Mapper.Map<IList<Destination>>(sources); List<Destination> listDests= Mapper.Map<List<Destination>>(sources); Destination[] destsArr= Mapper.Map<Destination[]>(sources); //這裡只舉兩個例子,其他集合同理 foreach (var dest in iCollectionDests) { Console.Write(dest.Value+","); } Console.WriteLine(); foreach (var dest in destsArr) { Console.Write(dest.Value + ","); } Console.Read(); } }
以上程式碼是集合和集合之間的對映,但是對映的配置CreateMap方法中只是配置的是型別之間的對映,而沒有設計任何集合型別。
測試結果如下,可見集合之間對映成功:
具體來說,支援的源集合型別包括:
- IEnumerable
- IEnumerable<T>
- ICollection
- ICollection<T>
- IList
- IList<T>
- List<T>
- Arrays
集合中的多型元素型別
很多時候,在我們的源和目標型別中可能有一個型別層次關係。AutoMapper支援多型陣列和集合,因此如果發現派生的源或者目標型別,就會使用它們。
public class ParentSource { public int Value1 { get; set; } } public class ChildSource : ParentSource { public int Value2 { get; set; } } public class ParentDestination { public int Value1 { get; set; } } public class ChildDestination : ParentDestination { public int Value2 { get; set; } }
AutoMapper仍然要求顯示配置孩子對映,因為它不能“猜出”具體使用哪一個孩子目標對映。
在Main方法中新增如下程式碼:
Mapper.Initialize(c => { c.CreateMap<ParentSource, ParentDestination>() .Include<ChildSource, ChildDestination>(); c.CreateMap<ChildSource, ChildDestination>(); }); var sources = new[] { new ParentSource(){Value1 = 11}, new ChildSource(){Value2 = 22}, new ParentSource(), }; var dests = Mapper.Map<ParentDestination[]>(sources); Console.WriteLine(dests[0]); Console.WriteLine(dests[1]); Console.WriteLine(dests[2]);
測試結果如下:
上面我們建立了一個源的陣列,其中包含兩個ParentSource和一個ChildSource,所以兩個ParentSource成功地對映到了ParentDestination,而CreateMap配置中,ParentSource到ParentDestination的對映配置包含了ChildSource到ChildDestination的配置,所以執行Mapper.Map<ParentDestination[]>(sources)的時候,也可以將ChildSource對映到ChildDestination。
對映繼承
在派生類中標明繼承
上面的程式碼,是在基類中配置繼承的,除此之外,也可以在派生類中配置繼承:
//在基類中配置繼承 Mapper.Initialize(c => { c.CreateMap<ParentSource, ParentDestination>() .Include<ChildSource, ChildDestination>(); c.CreateMap<ChildSource, ChildDestination>(); }); //在派生類中配置繼承 Mapper.Initialize(c => { c.CreateMap<ParentSource, ParentDestination>(); c.CreateMap<ChildSource, ChildDestination>() .IncludeBase<ParentSource, ParentDestination>(); });
繼承對映屬性
這裡介紹一下額外的複雜性,因為一個屬性對映時可以有多種方式。下面是這些源的優先順序:
- 顯式對映 (使用.MapFrom())
- 繼承的顯式對映
- 慣例對映 (通過慣例匹配的屬性)
- 忽略的屬性對映
下面來演示一下:
這裡還是用上面定義的四個類:Order,OrderDto,PCOrder,MobileOrder:
//領域物件 public class Order { } //電腦端訂單 public class PCOrder : Order { public string Referrer { get; set; } } //手機訂單 public class MobileOrder : Order { } //Dtos public class OrderDto { public string Referrer { get; set; } }
配置對映的方法使用的是在父類中配置繼承對映
//在父類中配置繼承對映 Mapper.CreateMap<Order, OrderDto>() .Include<PCOrder,OrderDto>() .Include<MobileOrder,OrderDto>() .ForMember(o => o.Referrer, m => m.Ignore());//這裡配置了忽略目標屬性Referrer的對映 Mapper.CreateMap<PCOrder,OrderDto>(); Mapper.CreateMap<MobileOrder, OrderDto>();
// 執行對映 var order = new PCOrder() { Referrer = "天貓" }; var mapped = Mapper.Map<OrderDto>(order); Console.WriteLine(mapped.Referrer);
執行結果如下:
注意在我們的對映配置中,我們已經忽略了Referrer
(因為Order基類中不存在這個屬性),但是在基類的對映中,慣例比忽略的屬性有更高的優先順序,因而屬性仍然得到了對映。