返回總目錄
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基類中不存在這個屬性),但是在基類的映射中,慣例比忽略的屬性有更高的優先級,因而屬性仍然得到了映射。