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方法中只是配置的是類型之間的映射,而沒有設計任何集合類型。
測試結果如下,可見集合之間映射成功:
具體來說,支持的源集合類型包括:
很多時候,在我們的源和目標類型中可能有一個類型層次關系。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>(); });
這里介紹一下額外的復雜性,因為一個屬性映射時可以有多種方式。下面是這些源的優先級:
下面來演示一下:
這里還是用上面定義的四個類:Order,OrderDto,PCOrder,MobileOrder:
//領域對象public class Order { }//電腦端訂單public class PCOrder : Order{ public string Referrer { get; set; }}//手機訂單public class MobileOrder : Order { }//Dtospublic 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基類中不存在這個屬性),但是在基類的映射中,慣例比忽略的屬性有更高的優先級,因而屬性仍然得到了映射。
新聞熱點
疑難解答