projectto c# automapper

projectto - c# automapper github



¿Puede Automapper mapear una lista paginada? (6)

AutoMapper maneja automáticamente las conversiones entre varios tipos de listas y matrices: http://automapper.codeplex.com/wikipage?title=Lists%20and%20Arrays

Parece que no convierte automáticamente los tipos personalizados de listas heredadas de IList, pero una solución alternativa podría ser:

var pagedListOfRequestForQuote = new PagedList<RequestForQuoteViewModel>( AutoMapper.Mapper.Map<List<RequestForQuote>, List<RequestForQuoteViewModel>>(((List<RequestForQuote>)requestForQuotes), page ?? 1, pageSize

Me gustaría asignar una lista paginada de objetos comerciales a una lista paginada de objetos del modelo de vista usando algo como esto:

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

La implementación de la lista paginada es similar a la implementación de Rob Conery aquí: http://blog.wekeroad.com/2007/12/10/aspnet-mvc-pagedlistt/

¿Cómo se puede configurar Automapper para hacer esto?


AutoMapper no admite esto de inmediato, ya que no conoce ninguna implementación de IPagedList<> . Sin embargo, tienes un par de opciones:

  1. Escriba un IObjectMapper personalizado, utilizando los Array / EnumerableMappers existentes como guía. Esta es la forma en que me gustaría ir personalmente.

  2. Escribe un TypeConverter personalizado, usando:

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

    y en el interior use Mapper.Map para mapear cada elemento de la lista.


Creé una pequeña envoltura alrededor de AutoMapper para asignar PagedList<DomainModel> a 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>(); } }

Uso:

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

¡Es importante que tengas que usar los tipos de elementos !

Si tiene alguna pregunta o sugerencia, no dude en comentar :)


Necesitaba devolver una versión serializable de IPagedList<> con AutoMapper versión 6.0.2 que soporta la interfaz IMapper para la API web de ASP.NET. Entonces, si la pregunta era cómo apoyo lo siguiente:

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

Entonces uno podría hacer esto:

Definir PagedViewModel<T>
Fuente: AutoMapper Custom Type Converter no funciona

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; } }

Escriba el convertidor genérico abierto de IPagedList<T> a PagedViewModel<T>
Fuente: 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" }; } }

Configurar mapeador

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 });


Si está utilizando la Lista de páginas de Troy Goode , hay una clase StaticPagedList que puede ayudarlo a mapear.

// 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());


Usando la respuesta de jrummell, creé un método de extensión que funciona con PagedList de Troy Goode . Te evita tener que poner tanto código en todas partes ...

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; }

El uso es:

var pagedDepartments = database.Departments.OrderBy(orderBy).ToPagedList(pageNumber, pageSize).ToMappedPagedList<Department, DepartmentViewModel>();