使用AutoMapper

一、AutoMapper初探

[参考Using AutoMapper: Getting Started]

1.新建空的ASP.NET MVC项目

2.在Models文件夹添加类

    public class Book
{
public string Title { get; set; }
}
    public class BookViewModel
{
public string Title { get; set; }
}

3.安装AtuoMapper

Install-Package AutoMapper

4.在App_Start文件夹添加配置类

    public static class AutoMapperConfig
{
public static void RegisterMappings()
{
AutoMapper.Mapper.CreateMap<Book, BookViewModel>();
}
}

5.在Global.asax中注册

AutoMapperConfig.RegisterMappings();

6.新建HomeController

        public string Index()
{
var book = new Book{Title="水浒传" };
var bookModel = AutoMapper.Mapper.Map<Book>(book);
return bookModel.Title;
}

7.运行程序

  aaarticlea/png;base64,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" alt="" />

二、创建映射

[参考Using AutoMapper: Creating Mappings]

1.CreateMap方法

  AutoMapper所有映射都是使用CreateMap方法定义的:

AutoMapper.Mapper.CreateMap<SourceClass, DestinationClass>();

  需要注意的是,上面定义的映射是单向映射。例如,我们定义了如下映射:

AutoMapper.Mapper.CreateMap<Book, BookViewModel>();

  我们可以将一个Book实例映射到一个BookViewModel实例:

var bookViewModel = AutoMapper.Mapper.Map<BookViewModel>(book);

  但是我们不能将一个BookViewModel实例映射到一个Book实例:

var book = AutoMapper.Mapper.Map<Book>(bookViewModel);

  如果要实现双向映射,需要再次调用CreateMap方法定义:

AutoMapper.Mapper.CreateMap<Book, BookViewModel>();
AutoMapper.Mapper.CreateMap<BookViewModel, Book>();

  如果我们不需要为反向映射定义任何自定义映射逻辑,我们可以使用ReverseMap实现双向映射:

AutoMapper.Mapper.CreateMap<Book, BookViewModel>().ReverseMap();

2.映射规则

  AutoMapper有一些映射约定,其中一个约定就是同名映射。例如:

public class Book
{
public string Title { get; set; }
} public class NiceBookViewModel
{
public string Title { get; set; }
} public class BadBookViewModel
{
public string BookTitle { get; set; }
}

  如果我们将一个Book实例映射到一个NiceBookViewModel实例,Title属性的值会是我们所期望的值。然而如果我们将一个Book实例映射到一个BadBookViewModel实例,Title属性的值会为null。因为名字不同,AutoMapper无从知晓BookTitle需要从Title获取值。这种情况下就需要我们手动添加配置代码:

AutoMapper.Mapper.CreateMap<Book, BadBookViewModel>()
.ForMember(dest => dest.BookTitle,
opts => opts.MapFrom(src => src.Title));

  另一个约定涉及到嵌入对象。例如:

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属性,但是它们的类型不匹配,因此AutoMapper不能将Book.Author映射到BookViewModel.Author。对于嵌入对象,AutoMapper的约定是目标类属性的命名为骆驼拼写法的“对象名+对象属性名”。示例如下:

public class BookViewModel
{
public string Title { get; set; }
public string AuthorName { get; set; }
}

  如果不采用约定,我们依然可以使用配置代码:

AutoMapper.Mapper.CreateMap<Book, BookViewModel>()
.ForMember(dest => dest.Author,
opts => opts.MapFrom(src => src.Author.Name));

3.投影

  在之前的示例中,如果我们把Author类修改为:

public class Author
{
public string FirstName { get; set; }
public string LastName { get; set; }
}

  我们需要将这两个属性映射到一个属性,代码如下:

AutoMapper.Mapper.CreateMap<Book, BookViewModel>()
.ForMember(dest => dest.Author,
opts => opts.MapFrom(
src => string.Format("{0} {1}",
src.Author.FirstName,
src.Author.LastName)));

4.更复杂的投影

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
}));

5.嵌套映射

  上面的示例中,如果PersonDTO修改为:

public class AddressDTO
{
public string Street { get; set; }
public string City { get; set; }
public string State { get; set; }
public string ZipCode { get; set; }
} public class PersonDTO
{
public string FirstName { get; set; }
public string LastName { get; set; }
public AddressDTO Address { get; set; }
}

  映射应该修改为:

AutoMapper.Mapper.CreateMap<PersonDTO, Person>();
AutoMapper.Mapper.CreateMap<AddressDTO, Address>();

三、映射到实例

[参考Using AutoMapper: Mapping Instances]

1.映射到新的实例

  之前的示例均产生一个新的实例,例如:

var destinationObject = AutoMapper.Mapper.Map<DestinatationClass>(sourceObject);

2.映射到已经存在的实例

AutoMapper.Mapper.Map(sourceObject, destinationObject);

3.映射到集合

var destinationList = AutoMapper.Mapper.Map<List<DestinationClass>>(sourceList);

  我们可以映射到所有的集合类型和接口:List<T>、ICollection<T>、IEnumerable<T>等。

  但是如果我们尝试映射到现有的实例:

AutoMapper.Mapper.Map(sourceList, destinationList);

  我们会发现destinationList已经被损坏。因为AutoMapper实际上是映射到集合而不是分别映射到集合中的对象。当我们考虑对象的层级结构时,这种情况就变得十分讨厌。例如:

public class Pet
{
public string Name { get; set; }
public string Breed { get; set; }
} public class Person
{
public List<Pet> Pets { get; set; }
} public class PetDTO
{
public string Name { get; set; }
public string Breed { get; set; }
} public class PersonDTO
{
public List<PetDTO> Pets { get; set; }
}

  如果我们创建一个只更新Name属性的表单,我们提交的对象图会是这样:

{
Pets: [
{ Name : "Sparky", Breed : null },
{ Name : "Felix", Breed : null },
{ Name : "Cujo", Breed : null }
]
}

  由于Breed属性没有被传递,它在每个PetDTO中的值为null。现在如果我们使用PersonDTO更新Person:

AutoMapper.Mapper.Map(person, personDTO);

  这样Person中每个Pet的Breed属性均变为null。这种问题解决起来有点麻烦,首先我们需要使用Ignore方法:

AutoMapper.Mapper.CreateMap<PersonDTO, Person>()
.ForMember(dest => dest.Pets,
opts => opts.Ignore());

  上面的代码告诉AutoMapper不映射Pets集合,这就意味着我们现在必须手动处理:

AutoMapper.Mapper.Map(person, personDTO);
for (int i = ; i < person.Pets.Count(); i++)
{
AutoMapper.Mapper.Map(person.Pets[i], personDTO.Pets[i]);
}

  上面的代码是基于假设两个list是相同的即我们没有对它们重新排序,并且不允许在表单添加或者删除项。为了解决重新排序后不一致的问题,我们需要依赖某些标识属性。例如:

var pet = person.Pets[i];
var updatedPet = personDTO.Pets.Single(m => m.Id == pet.Id);
AutoMapper.Mapper.Map(pet, updatedPet);

  添加或者删除项会更复杂一些:

var updatedPets = new List<Pet>();
foreach (var pet in personDTO.Pets)
{
var existingPet = person.Pets.SingleOrDefault(m => m.Id == pet.Id);
// No existing pet with this id, so add a new one
if (existingPet == null)
{
updatedPets.Add(AutoMapper.Mapper.Map<Pet>(pet));
}
// Existing pet found, so map to existing instance
else
{
AutoMapper.Mapper.Map(existingPet, pet);
updatedPets.Add(existingPet);
}
}
// Set pets to updated list (any removed items drop out naturally)
person.Pets = updatedPets;

  这可能是使用AutoMapper最大的难点,但是只要我们在执行更新操作的时候记得手动映射list项就行了。

上一篇:JavaWeb学习笔记——jquery中的dom操作


下一篇:转:DesiredCapabilities内容详解--Appium服务关键字