2010-01-15 207 views

回答

12

AutoMapper不支持開箱即用,因爲它不知道IPagedList<>的任何實現。然而,你有兩個選擇:

  1. 編寫自定義IObjectMapper,利用現有的磁盤陣列/ EnumerableMappers作爲指導。這是我個人的方式。

  2. 編寫自定義類型轉換器,使用:

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

    和內部使用Mapper.Map到列表中的每個元素映射。

+1

有人可以提供一個堅實的'PagedListTypeConverter'實現嗎? – 2012-09-12 12:52:09

+2

特洛伊古德的PagedList工作TypeConverter成一個簡單的ViewModel可以在這裏找到:http://stackoverflow.com/questions/12470156/automapper-custom-type-converter-not-working/12538611#12538611 – 2012-09-21 21:49:05

0

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 
+0

此方法失去'StartRecordIndex','EndRecordIndex','TotalItemCount'和'TotalPageCount'性質。 – 2012-09-12 12:32:51

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

它,你將不得不使用元素類型是很重要的!

如果您有任何問題或建議,請隨時發表評論:)

6

如果您使用Troy Goode's 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()); 
31

使用jrummell的回答,我創建了以Troy Goode's 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>(); 
+0

這節省了我很多寫作。 – 2012-09-19 14:47:18

+0

這對我有用! – Ryan 2012-11-25 02:31:38

+0

當你想讓AutoMapper忽略的字段時,這將如何工作? – Ciwan 2014-02-19 13:40:19

0

我需要返回IPagedList<>與AutoMapper版本6.0.2序列化的版本,支持IMapper ASP.NET Web API的接口。因此,如果這個問題是我怎麼支持以下內容:

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

那麼可以這樣做:

定義PagedViewModel<T>
來源:AutoMapper Custom Type Converter not working

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