Skip to content

denissden/AsyncMapper

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

57 Commits
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Асинхронный маппер

Расширяет функционал библиотеки AutoMapper добавляя асинхронность

Примеры использования Examples

Установка

Install-Package AsyncMapper

Пример:

var person = new Person() { name = "Иван", phone = "+7(916)123-45-67" };
Worker worker = await mapper.Map<Worker>(person);

Конфигурация

Маппер можно настроить двумя способами:

  • AsyncProfile - конфигурация находится в отдельных классах
public class ExampleProfile : AsyncProfile {
    public ExampleProfile() {
        /*конфигурация*/
    }
}
  • AsyncMapperConfiguration - в коде программы
var asyncConf = new AsyncMapperConfiguration(cfg => { /*конфигурация*/ });
var mapper = asyncConf.CreateAsyncMapper();

В AsyncMapperConfiguration можно подключить AsyncProfile с помощью cfg.AddAsyncProfile<TProfile>()

Создание мапы

CreateAsyncMap - создать мапу

Конфигурация происходит также, как в AutoMapper. Добавлены следующие расширения:

  • ForMemberAsync - конфигурация для отдельного поля/свойства
    • AddResolver - использовать резолвер
    • AddMemberResolver - использовать резолвер из указанного поля в указанное поле
  • AddAsyncResolver - эквивалент ForMemberAsync -> AddResolver
  • IncludeMap - эквивалент IncludeBase из AutoMapper
    • при использовании IncludeBase асинхронная конфигурация игнорируется

Пример

CreateAsyncMap<Person, Worker>()
    .ForMemberAsync(x => x.Phone, o => o.AddResolver<PersonToWorkerResolver>())
    .ForMemberAsync(x => x.Name, o => o.AddMemberResolver<LoginToNameResolver, string>(y => y.Login))
    .IncludeMap(typeof(PersonBase), typeof(WorkerBase))
    // конфигурация AutoMapper
    .ForMember(x => x.Id, o => o.MapFrom(y => y.Id))
    .ForMember(x => x.Email, o => o.MapFrom<PersonEmailResolver>())

Асинхронная конфигурация может быть смешана с синхронной в любом порядке

Внимание! Использование асинхронной конфигурации на синхронной мапе (CreateMap из AutoMapper) приведет к ошибке. Асинхронная мапа должна быть создана только через CreateAsyncMap.

Резолверы

  • IAsyncValueResolver - аналог IValueResolver
  • IAsyncMemberValueResolver - аналог IMemberValueResolver

Пример

public class ExampleResolver : IAsyncValueResolver<From, To, int> {
    public async Task<int> Resolve(From source, To destination) {
        /* код */
    }
}

public class ExampleMemberResolver : IAsyncMemberValueResolver<From, To, string, int> {
    public async Task<int> Resolve(From source, To destination, string sourceMember) {
        /* код */
    }
}

Внимание! В асинхронных резолверах функция Resolve должна выполняться асинхронно. Если на вашей функции Resolve висит варнинг CS1998, маппинг может выполняться медленнее.

Маппинг

Маппинг одного объекта

Task<TDestination> Map<TDestination>(object source);
Task<TDestination> Map<TSource, TDestination>(TSource source);
Task<TDestination> Map<TSource, TDestination>(TSource source, TDestination destination);

Маппинг нескольких объектов в IEnumerable

Task<IEnumerable<TDestination>> Map<TSource, TDestination>(IEnumerable<TSource> source);
Task<IEnumerable<TDestination>> Map<TDestination>(IEnumerable<object> source);

Чтобы получить доступ к синхронному мапперу, обращаемся к полю Sync

var workers = mapper.Sync.Map<Worker>(people);

Внимание! При сихронном маппинге асинхронная конфигурация игнорируется. Рекомендуется маппить синхронно только если мапа не содержит асинхронную конфигурацию (была создана с помощью CreateMap)

Dependency Injection

Install-Package AsyncMapper.DependencyInjection

Добавление сервиса маппера

services.AddAsyncMapper(typeof(ProfileMarkerType));

ProfileMarkerType - пустой класс, унаследованный от AsyncProfile. Используется для обозначения сборки, в которой находятся классы AsyncProfile с конфигурацией

ProfileMarkerType : AsyncProfile { }

Получение маппера

Маппер получается через интерфейс IAsyncMapper

ServiceProvider.GetService<IAsyncMapper>()

Резолверы

DI может быть использовано в резолверах

public class ExampleResolver : IAsyncValueResolver<...> {
    public ExampleResolver(IService service) {
        /* код */
    }
}

Переход проекта с синхронного маппера на асинхронный

Для корректной работы достаточно

  • Заменить сервис маппера в DI
  • Заменить наследование профилей с Profile на AsyncProfile
  • Маппинг (2 способа)
    • Заменить синхронный маппинг на асинхронный (mapper.Map(...) -> await mapper.Map(...))
    • Оставить синхронный маппинг (mapper.Map(...) -> mapper.Sync.Map(...))

Для увеличения производительности стоит перевести резолверы на асинхронность где это возможно

About

Async extensions for AutoMapper

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published