21

我想使用这样的方法将业务对象的分页列表映射到视图模型对象的分页列表:

var listViewModel = _mappingEngine.Map<IPagedList<RequestForQuote>, IPagedList<RequestForQuoteViewModel>>(requestForQuotes);

分页列表实现类似于 Rob Conery 的实现:http: //blog.wekeroad.com/2007/12/10/aspnet-mvc-pagedlistt/

你如何设置 Automapper 来做到这一点?

4

7 回答 7

36

使用 jrummell 的回答,我创建了一个与Troy Goode 的 PagedList一起使用的扩展方法。它使您不必在任何地方放置如此多的代码...

    public static IPagedList<TDestination> ToMappedPagedList<TSource, TDestination>(this IPagedList<TSource> list)
    {
        IEnumerable<TDestination> sourceList = Mapper.Map<IEnumerable<TSource>, IEnumerable<TDestination>>(list);
        IPagedList<TDestination> pagedResult = new StaticPagedList<TDestination>(sourceList, list.GetMetaData());
        return pagedResult;

    }

用法是:

var pagedDepartments = database.Departments.OrderBy(orderBy).ToPagedList(pageNumber, pageSize).ToMappedPagedList<Department, DepartmentViewModel>();
于 2012-09-17T16:18:54.317 回答
13

AutoMapper 不支持开箱即用,因为它不知道IPagedList<>. 但是,您确实有几个选择:

  1. IObjectMapper使用现有的 Array/EnumerableMappers 作为指南编写一个 custom 。这是我个人会走的路。

  2. 编写一个自定义 TypeConverter,使用:

    Mapper
        .CreateMap<IPagedList<Foo>, IPagedList<Bar>>()
        .ConvertUsing<MyCustomTypeConverter>();
    

    并在内部用于Mapper.Map映射列表的每个元素。

于 2010-01-17T19:50:30.443 回答
8

如果您使用的是Troy Goode 的 PageList,那么有一个StaticPagedList类可以帮助您进行映射。

// get your original paged list
IPagedList<Foo> pagedFoos = _repository.GetFoos(pageNumber, pageSize);
// map to IEnumerable
IEnumerable<Bar> bars = Mapper.Map<IEnumerable<Bar>>(pagedFoos);
// create an instance of StaticPagedList with the mapped IEnumerable and original IPagedList metadata
IPagedList<Bar> pagedBars = new StaticPagedList<Bar>(bars, pagedFoos.GetMetaData());
于 2012-03-09T15:03:31.677 回答
1

AutoMapper 自动处理几种类型的列表和数组之间的转换: http ://automapper.codeplex.com/wikipage?title=Lists%20and%20Arrays

它似乎不会自动转换从 IList 继承的自定义列表类型,但解决方法可能是:

    var pagedListOfRequestForQuote = new PagedList<RequestForQuoteViewModel>(
        AutoMapper.Mapper.Map<List<RequestForQuote>, List<RequestForQuoteViewModel>>(((List<RequestForQuote>)requestForQuotes),
        page ?? 1,
        pageSize
于 2010-01-15T17:52:45.413 回答
1

我围绕 AutoMapper 创建了一个小包装器以映射PagedList<DomainModel>PagedList<ViewModel>.

public class MappingService : IMappingService
{
    public static Func<object, Type, Type, object> AutoMap = (a, b, c) =>
    {
        throw new InvalidOperationException(
            "The Mapping function must be set on the MappingService class");
    };

    public PagedList<TDestinationElement> MapToViewModelPagedList<TSourceElement, TDestinationElement>(PagedList<TSourceElement> model)
    {
        var mappedList = MapPagedListElements<TSourceElement, TDestinationElement>(model);
        var index = model.PagerInfo.PageIndex;
        var pageSize = model.PagerInfo.PageSize;
        var totalCount = model.PagerInfo.TotalCount;

        return new PagedList<TDestinationElement>(mappedList, index, pageSize, totalCount);
    }

    public object Map<TSource, TDestination>(TSource model)
    {
        return AutoMap(model, typeof(TSource), typeof(TDestination));
    }

    public object Map(object source, Type sourceType, Type destinationType)
    {
        if (source is IPagedList)
        {
            throw new NotSupportedException(
                "Parameter source of type IPagedList is not supported. Please use MapToViewModelPagedList instead");
        }

        if (source is IEnumerable)
        {
            IEnumerable<object> input = ((IEnumerable)source).OfType<object>();
            Array a = Array.CreateInstance(destinationType.GetElementType(), input.Count());

            int index = 0;
            foreach (object data in input)
            {
                a.SetValue(AutoMap(data, data.GetType(), destinationType.GetElementType()), index);
                index++;
            }
            return a;
        }

        return AutoMap(source, sourceType, destinationType);
    }

    private static IEnumerable<TDestinationElement> MapPagedListElements<TSourceElement, TDestinationElement>(IEnumerable<TSourceElement> model)
    {
        return model.Select(element => AutoMap(element, typeof(TSourceElement), typeof(TDestinationElement))).OfType<TDestinationElement>();
    }
}

用法:

PagedList<Article> pagedlist = repository.GetPagedList(page, pageSize);
mappingService.MapToViewModelPagedList<Article, ArticleViewModel>(pagedList);

重要的是您必须使用元素类型!

如果您有任何问题或建议,请随时发表评论:)

于 2010-11-01T21:45:57.320 回答
1

使用 Automapper .net core 8.1.1 很容易

您只需将类型映射添加到您的 mapperProfile 并将对象映射到 pagedList

CreateMap(typeof(IPagedList<>), typeof(IPagedList<>));
CreateMap<RequestForQuote, RequestForQuoteViewModel>().ReverseMap();

它也可以是和PagedList一样的抽象类。它与类/接口类型无关

您可以直接在 mapper.Map 中使用它 - 在类构造函数中从 IMapper 初始化映射器

RequestForQuote result
_mapper.Map<IPagedList<RequestForQuoteViewModel>>(result);
于 2021-12-14T22:31:39.717 回答
0

我需要返回支持ASP.NET Web API 接口的IPagedList<>AutoMapper 版本 6.0.2的可序列化版本。IMapper因此,如果问题是我如何支持以下内容:

//Mapping from an enumerable of "foo" to a different enumerable of "bar"...
var listViewModel = _mappingEngine.Map<IPagedList<RequestForQuote>, PagedViewModel<RequestForQuoteViewModel>>(requestForQuotes);

然后可以这样做:

定义PagedViewModel<T>
源:AutoMapper 自定义类型转换器不起作用

public class PagedViewModel<T>
{
    public int FirstItemOnPage { get; set; }
    public bool HasNextPage { get; set; }
    public bool HasPreviousPage { get; set; }
    public bool IsFirstPage { get; set; }
    public bool IsLastPage { get; set; }
    public int LastItemOnPage { get; set; }
    public int PageCount { get; set; }
    public int PageNumber { get; set; }
    public int PageSize { get; set; }
    public int TotalItemCount { get; set; }
    public IEnumerable<T> Subset { get; set; }
}

IPagedList<T>PagedViewModel<T>源代码编写开放通用转换器: https ://github.com/AutoMapper/AutoMapper/wiki/Open-Generics

public class Converter<TSource, TDestination> : ITypeConverter<IPagedList<TSource>, PagedViewModel<TDestination>>
{
    public PagedViewModel<TDestination> Convert(IPagedList<TSource> source, PagedViewModel<TDestination> destination, ResolutionContext context)
    {
        return new PagedViewModel<TDestination>()
        {
            FirstItemOnPage = source.FirstItemOnPage,
            HasNextPage = source.HasNextPage,
            HasPreviousPage = source.HasPreviousPage,
            IsFirstPage = source.IsFirstPage,
            IsLastPage = source.IsLastPage,
            LastItemOnPage = source.LastItemOnPage,
            PageCount = source.PageCount,
            PageNumber = source.PageNumber,
            PageSize = source.PageSize,
            TotalItemCount = source.TotalItemCount,
            Subset = context.Mapper.Map<IEnumerable<TSource>, IEnumerable<TDestination>>(source) //User mapper to go from "foo" to "bar"
        };
    }
}

配置映射器

new MapperConfiguration(cfg =>
    {
        cfg.CreateMap<RequestForQuote, RequestForQuoteViewModel>();//Define each object you need to map
        cfg.CreateMap(typeof(IPagedList<>), typeof(PagedViewModel<>)).ConvertUsing(typeof(Converter<,>)); //Define open generic mapping
    });
于 2017-05-30T18:37:49.967 回答