Кто нибудь может поделиться опытом, как мапить PagedList на PagedList с AutoMapper?

Я пытаюсь следовать этому ответу. Но то что там предложено, не работает. Или я не понимаю до конца, как оно должно работать. Итак, у меня задача. Смапить PagedList объектов бизнес-логики на PagedList объектов view модели.

Вот мой метод действия контроллера:

public async Task<IActionResult> Index(int pageNumber = 1, bool showActive = true)
{
    var manuallySendings = _dbContext.ManuallySendings
        .Include(x => x.Messages)
        .ThenInclude(x => x.PushLang).Where(x => x.IsActive == showActive);

    var manuallySendingsPagedList = await manuallySendings.ToPagedListAsync(pageNumber, 15);


    var viewModelsPagedList =  _mapper.Map<IPagedList<ManuallySending>, IPagedList<ManuallySendingIndexViewModel>>(manuallySendingsPagedList);
    return View(viewModelsPagedList);
}

Вот профайл для мапинга бизнес-объекта на модель представления

public class ManuallySendingToManuallySendingIndexPageItem : Profile
{
    public ManuallySendingToManuallySendingIndexPageItem()
    {
        CreateMap<ManuallySending, ManuallySendingIndexViewModel>()
            .ForMember(dest => dest.PackageIds,
                opt 
                    => opt.MapFrom(x => x.PackageIds))
            // more .ForMember ...
            .ConvertUsing<PagedListConverter>();
    }
}

И, обратите внимание, на вызов в конце ConvertUsing. Он же должен объяснить автомапперу, как мапить этот тип, верно?

А вот мой кстомный конвертор:

public class PagedListConverter : ITypeConverter<PagedList<ManuallySending>,PagedList<ManuallySendingIndexViewModel>>
{
    public PagedList<ManuallySendingIndexViewModel> Convert(PagedList<ManuallySending> source, 
        PagedList<ManuallySendingIndexViewModel> destination, ResolutionContext context)
    {
        var vm = source.Select(m 
            => context.Mapper.Map<ManuallySending, ManuallySendingIndexViewModel>(m)).ToList();

        return new PagedList<ManuallySendingIndexViewModel>(vm, source.PageNumber, source.PageSize);
    }
}

Но я даже запустить это не могу. IDE говорит мне:

ManuallySendingToManuallySendingIndexPageItem.cs(18, 18): [CS0311] Тип "AdminPanel.Automapper.PagedListConverter" не может быть использован как параметр типа "TTypeConverter" в универсальном типе или методе "IMappingExpressionBase>.ConvertUsing()". Нет преобразования неявной ссылки из "AdminPanel.Automapper.PagedListConverter" в "AutoMapper.ITypeConverter".

Нажимаю alt + enter пользуюсь подсказкой. Мне предлагается изменить интерфейс конвертора с ITypeConverter<PagedList<ManuallySending>,PagedList<ManuallySendingIndexViewModel>> на ITypeConverter<ManuallySending, ManuallySendingIndexViewModel>

Но как я из этого сделаю PagedList? Не понимаю :( Помогите, пожалуйста. Думаю, решение поможет многим, кто на это наткнется в дальнейшем.

P.S Я использую автомаппер последней версии и .net core 3.1. Все самое новое.


Ответы (1 шт):

Автор решения: Aleksej_Shherbak

Итак, после некоторого ресерча и микса нескольких решений со SO я пришел вот к такому "дженерик" конвертору и способу его использования.

1) Обязательно иметь обычный профайлер business object -> view model object. Смотрите подробности в документации вот ссылка.

2) Сделаем еще один профайлер, где объясним мапперу, что мы хотим не просто эти объекты мапить, а их paged листы. Согласно моему нейменгу и коду из вопроса, он у меня выглядит так:

public class PagedListToPagedList : Profile
{
    public PagedListToPagedList()
    {
        CreateMap<IPagedList<ManuallySending>, IPagedList<ManuallySendingIndexViewModel>>()
            .ConvertUsing<PagedListConverter<ManuallySending, ManuallySendingIndexViewModel>>();
    }
}

3) А теперь самое интересное. Видите, мы тут сказали автомапперу, что конвертр будем использовать? (вызов ConvertUsing). Напишем этот дженерик конвертр. Он у меня вот такой получился.

public class
    PagedListConverter<TSource, TDestination> : ITypeConverter<IPagedList<TSource>, IPagedList<TDestination>>
    where TSource : class where TDestination : class
{
    public IPagedList<TDestination> Convert(IPagedList<TSource> source,
        IPagedList<TDestination> destination, ResolutionContext context)
    {
        var vm = source.Select(m
            => context.Mapper.Map<TSource, TDestination>(m)).ToList();

        return new StaticPagedList<TDestination>(vm, source.GetMetaData());
    }
}

В отличии о того способа, что указан по ссылке на англоязычный SO в моем вопросе, тут у меня не теряется количество страниц и пагинация отрабатывает корректно! Всем спасибо, надеюсь, что это кому то поможет!

→ Ссылка