Automapper接口映射

3

我有一个PagedList实现,想要使用AutoMapper将实体PagedList映射到DTO PagedList。以下是我的接口:

public interface IPagedList<T> : IList<T>
{
    PagingInformation Paging { get; set; }
}

这是我的类实现:

public class PagedList<T> : List<T>, IPagedList<T> //, IList<T>
{
    public PagingInformation Paging { get; set; }

    public PagedList()
    {
    }

    public PagedList(IEnumerable<T> collection) : base(collection)
    {
    }

    public PagedList(IEnumerable<T> collection, PagingInformation paging) : base(collection)
    {
        Paging = paging;
    }

    public PagedList(int capacity) : base(capacity)
    {
    }

    PagingInformation IPagedList<T>.Paging
    {
        get => Paging;
        set => Paging = value;
    }

    IEnumerator IEnumerable.GetEnumerator()
    {
        return GetEnumerator();
    }


}

我正在使用Automapper,类似于:

public async Task<DomainResult<IPagedList<PositionDto>>> GetPagedListAsync(int pageIndex = 0, int pageSize = 20)
{
    return DomainResult<IPagedList<PositionDto>>.Success(_mapper.Map<IPagedList<PositionDto>>(await _positionRepository.GetPagedListAsync(pageIndex, pageSize)));
}

没有Mapper配置: 我得到以下错误:
映射类型错误。 映射类型:PagedList <1-> IPagedList 1 WestCore.Shared.Collections.Pagination.PagedList <1 [[WestCore.Domain.Entities.Position, WestCore.Domain,Version = 1.0.0.0,Culture = neutral, PublicKeyToken = null]]-> WestCore.Shared.Collections.Pagination.IPagedList 1 [[WestCore.AppCore.Models.PositionDto, WestCore.AppCore,Version = 1.0.0.0,Culture = neutral, PublicKeyToken = null]]
当我将 CreateMap(typeof(PagedList << >>),typeof(IPagedList << >>))添加到Mapper Pofile中时,我得到以下错误:
程序集'AutoMapper.Proxies,Version = 0.0.0.0,Culture = neutral, PublicKeyToken = be96cd2c38ef1005'中类型“Proxy WestCore.Shared.Collections.Pagination.IPagedList`1[[WestCore.AppCore.Models.PositionDto_WestCore.AppCore_Version=1.0.0.0_Culture=neutral_PublicKeyToken=null]]_WestCore.Shared_Version=1.0.0.0_Culture=neutral_PublicKeyToken=null”的方法“get_Item”没有实现。
当我将 CreateMap(typeof(PagedList << >>),typeof(IPagedList << >>)).As(typeof(PagedList << >>))添加到Mapper Profile中时,我不会出错,但是PagedList返回空结果集
我不确定是否在 PagedList 方法中缺少实现,或者它是一个配置问题。
编辑:
下面添加了分页信息:
    public class PagingInformation
{
    /// <summary>
    /// Gets the index start value.
    /// </summary>
    /// <value>The index start value.</value>
    public int IndexFrom { get; }

    /// <summary>
    /// Gets the page index (current).
    /// </summary>
    public int PageIndex { get; }

    /// <summary>
    /// Gets the page size.
    /// </summary>
    public int PageSize { get; }

    /// <summary>
    /// Gets the total count of the list of type <typeparamref name="TEntity"/>
    /// </summary>
    public int TotalCount { get; }

    /// <summary>
    /// Gets the total pages.
    /// </summary>
    public int TotalPages { get; }

    /// <summary>
    /// Gets the has previous page.
    /// </summary>
    /// <value>The has previous page.</value>
    public bool HasPreviousPage => PageIndex - IndexFrom > 0;

    /// <summary>
    /// Gets the has next page.
    /// </summary>
    /// <value>The has next page.</value>
    public bool HasNextPage => PageIndex - IndexFrom + 1 < TotalPages;

    public PagingInformation(int pageIndex, int pageSize, int indexFrom, int count)
    {
        if (indexFrom > pageIndex)
        {
            throw new ArgumentException($"indexFrom: {indexFrom} > pageIndex: {pageIndex}, must indexFrom <= pageIndex");
        }

        PageIndex = pageIndex;
        PageSize = pageSize;
        IndexFrom = indexFrom;
        TotalCount = count;
        TotalPages = (int) Math.Ceiling(TotalCount / (double) PageSize);

    }
}

谢谢你。
感谢您。
2个回答

5

由于映射器不知道如何创建接口的实例,因此您无法将接口用作映射的结果。

您可以使用ConstructUsing创建IPagedList。例如:

AutoMapper.Mapper.CreateMap<DtoParent, ICoreParent>()
            .ConstructUsing(parentDto => new CoreParent())
            .ForMember(dest => dest.Other, opt => opt.MapFrom(src => AutoMapper.Mapper.Map<DtoChild, ICoreChild>(src.Other)));

编辑:

按照以下方式操作:

class Example
{
    static void Main()
    {
        AutoMapper.Mapper.Initialize(config =>
        {
            config.CreateMap(typeof(PagedList<>), typeof(IPagedList<>))
                 .ConvertUsing(typeof(Converter<,>));

            config.CreateMap<Entity, DTO>();

        });

        var entityList = new PagedList<Entity>(new [] { new Entity(), }, new PagingInformation() { Total =  2, PageNumber =  1, PageSize = 10});

        var mapped = Mapper.Map<IPagedList<DTO>>(entityList);
    }
}

class Converter<TSource, TDest> : ITypeConverter<IPagedList<TSource> , IPagedList<TDest>>
{
    public IPagedList<TDest> Convert(IPagedList<TSource> source, IPagedList<TDest> destination, ResolutionContext context) =>  new PagedList<TDest>(context.Mapper.Map<IEnumerable<TDest>>(source.AsEnumerable()), source.Paging);
}

class Entity
{
    public Guid Id { get; set; } = Guid.NewGuid();
}

class DTO
{
    public Guid Id { get; set; } = Guid.NewGuid();
}

public interface IPagedList<T> : IList<T>
{
    PagingInformation Paging { get; set; }
}

public class PagingInformation
{
    public int Total { get; set; }

    public int PageSize { get; set; }

    public int PageNumber { get; set; }
}

public class PagedList<T> : List<T>, IPagedList<T>
{
    public PagingInformation Paging { get; set; }

    public PagedList() { }
    public PagedList(IEnumerable<T> collection) : base(collection) { }

    public PagedList(IEnumerable<T> collection, PagingInformation paging) : base(collection) { Paging = paging; }
}

也许这需要以某种其他方式映射PagingInformation,因为在我的例子中,两个分页列表在映射后都引用了同一个PagingInformation对象,我认为这是可以的,只要PagingInformation是不可变的。

我的PagedList方法具有泛型类型,因此我无法使用ConstructUsing方法。我相信一定有更简单的方法来解决这个问题。 - Derviş Kayımbaşıoğlu
反射?……不是很好的解决方案,但应该会有所帮助。我会再多考虑一下。 - Alex Lyalka
请问您能否添加PagingInformation类的定义?这个类预计用于保存页面编号、数量等信息。 - Alex Lyalka
添加到原始帖子中。我可能会使用反射,但据我了解,我将需要非泛型基础方法。我不确定我将如何实现它。 - Derviş Kayımbaşıoğlu
它起作用了,事实上我没有使用setter。它完美地运行了。谢谢你。 - Derviş Kayımbaşıoğlu

1
假设您知道要使用的实现方式,您可以在映射时提供类型,如下所示。
var mapper = new AutoMapper.MapperConfiguration(m => m.CreateMap<DtoParent, ICoreParent>()).CreateMapper();
var result = mapper.Map(new DtoParent { Name = "Billy Bob" }, new CoreParent());

我发现这种方法在我有多个实现并且没有很好的设置映射时特别灵活。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接