Расширяет функционал библиотеки 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
)
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(...)
)
- Заменить синхронный маппинг на асинхронный (
Для увеличения производительности стоит перевести резолверы на асинхронность где это возможно