上一篇文章中,我們知道了如何在asp.net中使用Automapper,這次,我們進(jìn)行深入了解
CreateMap方法
CreateMap是一個(gè)單向mapping,也就是說(shuō),如果定義了這樣的mapper:
AutoMapper.Mapper.CreateMap<Book, BookViewModel>();
我們就可以將Book映射到BookViewModel: var bookViewModel = AutoMapper.Mapper.Map<BookViewModel>(book);; 但是,如果反向映射,則會(huì)報(bào)錯(cuò):var book = AutoMapper.Mapper.Map<Book>(bookViewModel);.
我們當(dāng)然可以定義多個(gè)映射:
AutoMapper.Mapper.CreateMap<Book, BookViewModel>();
AutoMapper.Mapper.CreateMap<BookViewModel, Book>();
但如果兩個(gè)類沒(méi)有什么特殊轉(zhuǎn)換,我們也可以簡(jiǎn)單的使用reverse映射:
AutoMapper.Mapper.CreateMap<Book, BookViewModel>().ReverseMap();
這樣兩個(gè)類就可以來(lái)回互轉(zhuǎn)了。
Conventions-約定
Automapper的最基本約定是,轉(zhuǎn)換源和目標(biāo)的字段名相同時(shí)將會(huì)自動(dòng)對(duì)應(yīng):
public class Book
{
public string Title { get; set; }
}
public class NiceBookViewModel
{
public string Title { get; set; }
}
public class BadBookViewModel
{
public string BookTitle { get; set; }
}
按照約定,NiceBookViewModel和Book類具有相同字段,可以自動(dòng)mapping,但是BadBookViewModel字段名不一致所以無(wú)法對(duì)應(yīng)。我們就必須自定義映射關(guān)系:
AutoMapper.Mapper.CreateMap<Book, BadBookViewModel>()
.ForMember(dest => dest.BookTitle,
opts => opts.MapFrom(src => src.Title));
另一個(gè)約定是包含類名稱約定,如:
public class Author
{
public string Name { get; set; }
}
public class Book
{
public string Title { get; set; }
public Author Author { get; set; }
}
public class BookViewModel
{
public string Title { get; set; }
public string Author { get; set; }
}
盡管Book類和BookViewModel類都含有Author,(一個(gè)是類名,一個(gè)是字段名),automaper都無(wú)法自動(dòng)映射。但如果我們對(duì)BookViewModel稍作修改:
public class BookViewModel
{
public string Title { get; set; }
public string AuthorName { get; set; }
}
即可以了。其實(shí)AuthorName字段就相當(dāng)于Author.Name。
這種約定雖然方便,但還是建議大家手動(dòng)指定mapper放心一點(diǎn):
AutoMapper.Mapper.CreateMap<Book, BookViewModel>()
.ForMember(dest => dest.Author,
opts => opts.MapFrom(src => src.Author.Name));
復(fù)雜映射
如果Author類是這個(gè)樣子:
public class Author
{
public string FirstName { get; set; }
public string LastName { get; set; }
}
而我們想將其映射到BookViewModel中,而且用BookViewModel中的一個(gè)字段包含全名,該怎么做呢?
AutoMapper.Mapper.CreateMap<Book, BookViewModel>()
.ForMember(dest => dest.Author,
opts => opts.MapFrom(
src => string.Format("{0} {1}",
src.Author.FirstName,
src.Author.LastName)));
對(duì)目標(biāo)類中的Author字段,我們使用源類中的FirstName+LastName進(jìn)行替換。
更加復(fù)雜的映射
上面的例子是將源類在目標(biāo)類中進(jìn)行組合,如果我們想使用源類“組合”成目標(biāo)類怎么辦呢?
public class Address
{
public string Street { get; set; }
public string City { get; set; }
public string State { get; set; }
public string ZipCode { get; set; }
}
public class Person
{
public string FirstName { get; set; }
public string LastName { get; set; }
public Address Address { get; set; }
}
public class PersonDTO
{
public string FirstName { get; set; }
public string LastName { get; set; }
public string Street { get; set; }
public string City { get; set; }
public string State { get; set; }
public string ZipCode { get; set; }
}
我們想建立PersonDTO→Person類映射,那可以這樣:
AutoMapper.Mapper.CreateMap<PersonDTO, Person>()
.ForMember(dest => dest.Address,
opts => opts.MapFrom(
src => new Address
{
Street = src.Street,
City = src.City,
State = src.State,
ZipCode = src.ZipCode
}));
BTW,這種情況非常多見(jiàn),前臺(tái)傳進(jìn)來(lái)的表單字段(PersonDTO),可以通過(guò)mapping自動(dòng)組成復(fù)雜類(Person),爽歪歪。
mapping到新實(shí)例 vs mapping到已有實(shí)例
類似這樣:var destinationObject = AutoMapper.Mapper.Map<DestinatationClass>(sourceObject);的語(yǔ)法,舉例:var model = Mapper.Map<BookViewModel>(book);我們將創(chuàng)建一個(gè)目標(biāo)類的新實(shí)例。
但有時(shí)我們不想創(chuàng)建新實(shí)例,比如在Update時(shí),那我們可以用這樣的語(yǔ)法:AutoMapper.Mapper.Map(sourceObject, destinationObject);; 舉例:Mapper.Map<BookViewModel>(book,bookViewModel)
數(shù)組/列表的mapping
一般情況下,當(dāng)定義好了mapper,列表就可以被自動(dòng)mapping,不需要額外代碼
var destinationList = AutoMapper.Mapper.Map<List<DestinationClass>>(sourceList);
適用于所有集合類型: List<T>, ICollection<T>, IEnumerable<T>, etc.