Как стать автором
Обновить

AutoMapper: добавление и использование в проекте ASP.Net Core

Время на прочтение4 мин
Количество просмотров47K

При работе с данными (и не только) нам часто приходится сталкиваться с необходимостью копирования (маппинга) значений свойств одного объекта в новый объект другого типа.

Например предположим, что запрос к базе данных возвращает нам запись в виде объекта, представленного классом Person:

public class Person
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public DateTime BirthDate { get; set; }
}

Далее нам необходимо создать новый объект, представленный классом Student:

public class Student
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public DateTime BirthDate { get; set; }
    public DateTime AdmissionDate { get; set; }
}

 и скопировать в его свойства данные из свойств полученного из БД объекта.

Без помощи сторонней библиотеки нам пришлось бы сделать это самим:

// получаем запись из БД
var person = _dbRepository.GetPerson(1);

// копируем значения свойств (осуществляем маппинг)
var student = new Student
{
    FirstName = person.FirstName,
    LastName = person.LastName,
    BirthDate = person.BirthDate
};

А с использованием библиотеки AutoMapper, маппинг производится всего одной строкой кода:

var student = _mapper.Map<Student>(person);

1. Подключение библиотеки AutoMapper к проекту и ее использование

Шаг 1

Добавление в проект NuGet пакетов:

·         AutoMapper

·         AutoMapper.Extensions.Microsoft.DependencyInjection

Для этого в SolutionExplorer (Обозреватель решений) правой кнопкой мыши жмем по названию рабочего проекта и выбираем Manage NuGet Packages… (Управление пакетами Nuget).

 Далее переходим на крайнюю левую вкладку Browse, и в строку поиска вводим название устанавливаемого пакета NuGet.

В левом окне выбираем нужный нам пакет, а в правом жмем кнопку Install.

Дожидаемся окончания установки.

Проделываем эти действия для обоих пакетов.

Шаг 2

Добавляем в проект класс AppMappingProfile:

public class AppMappingProfile : Profile
{
		public AppMappingProfile()
		{			
			CreateMap<Person, Student>();
		}
}

В generics метода CreateMap первым передаем тип-источник значений, вторым – тип-приемник.

Т.е. в данном примере мы задаем маппинг из объекта Person в объект Student.

Если мы хотим, чтобы маппинг работал в обоих направлениях, добавляем вызов метода-расширения ReverseMap():

CreateMap<Person, Student>().ReverseMap();

Теперь мы можем также маппить объект student в объект person:

var person = _mapper.Map<Person>(student);

Шаг 3

Добавляем AutoMapper в DI контейнер. Для этого в метод ConfigureServices класса Startup.cs добавляем строку:

public void ConfigureServices(IServiceCollection services)
{
  // другой код
  services.AddAutoMapper(typeof(AppMappingProfile));
  // другой код
}

Классов маппинг-профайлов может быть создано несколько. В таком случае, передаем их в параметры метода AddAutoMapper через запятую:

services.AddAutoMapper(typeof(AppMappingProfile), typeof(MappingProfile2));

Шаг 4

Используем маппер.

Теперь маппинг нашего объекта Person в Student происходит в одну строку кода:

var student = _mapper.Map<Student>(person);

Ниже приведен полный код класса, использующего маппинг:

using AutoMapper;
using AutoMapperInAspNetCore.Db;
using AutoMapperInAspNetCore.Models;

namespace AutoMapperInAspNetCore.Mapping
{
    public class MappingHelper
    {
        private readonly IMapper _mapper;
        private readonly IDbRepository _dbRepository;

        public MappingHelper(IMapper mapper, IDbRepository dbRepository)
        {
            _mapper = mapper;
            _dbRepository = dbRepository;
        }

        public void DoSomething()
        {
            // получаем запись из БД
            var person = _dbRepository.GetPerson(1);

            // Создаем новый объект типа Student и копируем в его свойства
     				// значения свойств объекта person (осуществляем маппинг)
            var student = _mapper.Map<Student>(person);
        }
    }
}

Здесь в качестве generic в метод Map объекта _mapper передаем тип-приемник (Student), а в пераметре передаем объект-источник (person).

Теперь мы имеем объект student типа Student, со значениями полей из объекта person.

При этом мапятся только те поля, названия которых полностью совпадают у обоих типов.

В данном случае – это поля:

public string FirstName { get; set; }
public string LastName { get; set; }
public DateTime BirthDate { get; set; }

2. Маппинг объектов с не совпадающими наименованиями свойств

Для наглядности немного видоизменим класс Student, переименовав его свойства:

public class Student
{
    public string Fio { get; set; }
    public DateTime Birthday { get; set; }
    public DateTime AdmissionDate { get; set; }
}

Теперь наименования свойств объектов person и student не совпадают.

Для того, чтобы маппинг заработал, нам придется дописать в маппинг-профайле  явные правила:

public AppMappingProfile()
{	  
  CreateMap<Person, Student>()
    .ForMember(dest => dest.Fio, opt => opt.MapFrom(src => $"{src.FirstName} {src.LastName}"))
    .ForMember(dest => dest.Birthday, opt => opt.MapFrom(src => src.BirthDate));
}

где параметр dest представляет собой объект-приемник, а src – объект-источник.

В методе MapFrom для поля Fio объекта student мы применили интерполяцию строки –

$"{src.FirstName} {src.LastName}"

результатом которой будет строка вида «Имя Отчество», которая и присвоится свойству Fio объекта student.

PS: Данный туториал рассчитан в первую очередь на уже знакомую с предназначением описываемой технологии аудиторию и представляет из себя краткое руководство по быстрому применению базового функционала этой технологии в своих проектах. Туториал не претендует на полное и исчерпывающее пособие по затронутой тематике и не является рекламой. Идея написания этой, и серии подобных статей, была подсказана студентами, не владеющими в должной мере английским языком и испытывающими определенные трудности при поиске такого рода информации на просторах рунета.

Теги:
Хабы:
Всего голосов 4: ↑2 и ↓20
Комментарии38

Публикации