2012-08-05 73 views
5

我開始執行AutoMapper,首先我設法將它與Castle.Windsor集成,我已經使用它。現在我有一個Post實體,我想要映射到​​或ImagePostModel。無論從PostModelAutoMapper根據枚舉映射到不同的類型?

1)繼承這是我到目前爲止有:

public class PostModelFromPostEntityConverter : ITypeConverter<Post, PostModel> 
{ 
    private readonly IPostService postService; 

    public PostModelFromPostEntityConverter(IPostService postService) 
    { 
     if (postService == null) 
     { 
      throw new ArgumentNullException("postService"); 
     } 
     this.postService = postService; 
    } 

    public PostModel Convert(ResolutionContext context) 
    { 
     Post post = (Post)context.SourceValue; 
     Link link = post.Link; 
     if (link.Type == LinkType.Html) 
     { 
      return new LinkPostModel 
      { 
       Description = link.Description, 
       PictureUrl = link.Picture, 
       PostId = post.Id, 
       PostSlug = postService.GetTitleSlug(post), 
       Timestamp = post.Created, 
       Title = link.Title, 
       UserMessage = post.UserMessage, 
       UserDisplayName = post.User.DisplayName 
      }; 
     } 
     else if (link.Type == LinkType.Image) 
     { 
      return new ImagePostModel 
      { 
       PictureUrl = link.Picture, 
       PostId = post.Id, 
       PostSlug = postService.GetTitleSlug(post), 
       Timestamp = post.Created, 
       UserMessage = post.UserMessage, 
       UserDisplayName = post.User.DisplayName 
      }; 
     } 
     return null; 
    } 
} 

顯然在實施AutoMapper點是消除這樣的重複代碼,所以我怎麼映射的共同的東西,加入我的自定義規則(如if子句)之前

理想我想這是這樣的:

public class PostModelFromPostEntityConverter : ITypeConverter<Post, PostModel> 
{ 
    [...] 

    public PostModel Convert(ResolutionContext context) 
    { 
     Post post = (Post)context.SourceValue; 
     Link link = post.Link; 
     if (link.Type == LinkType.Html) 
     { 
      return Mapper.Map<Post, LinkPostModel>(post); 
      // and a few ForMember calls? 
     } 
     else if (link.Type == LinkType.Image) 
     { 
      return Mapper.Map<Post, ImagePostModel>(post); 
      // and a few ForMember calls? 
     } 
     return null; 
    } 
} 

2)此映射完成後。我有一個「父」的映射,在這裏我需要映射一個IEnumerable<Post>以下模型:

public class PostListModel : IHasOpenGraphMetadata 
{ 
    public OpenGraphModel OpenGraph { get; set; } // og:model just describes the latest post 
    public IList<PostModel> Posts { get; set; } 
} 

所以基本上我需要另一個TypeConverter(右?),這讓我首先映射的職位列表,然後創建og:model

我有這個,但它那種感覺笨重,我覺得還可以更好:

public class PostListModelFromPostEntityEnumerableConverter : ITypeConverter<IEnumerable<Post>, PostListModel> 
{ 
    public PostListModel Convert(ResolutionContext context) 
    { 
     IEnumerable<Post> posts = (IEnumerable<Post>)context.SourceValue; 
     PostListModel result = new PostListModel 
     { 
      Posts = posts.Select(Mapper.Map<Post, PostModel>).ToList() 
     }; 
     Post first = posts.FirstOrDefault(); 
     result.OpenGraph = Mapper.Map<Post, OpenGraphModel>(first); 
     return result; 
    } 
} 

3)我實際上並沒有運行代碼,所以想到另一個問題,那就是爲什麼轉換器中沒有強類型的映射?

IEnumerable<Post> posts = (IEnumerable<Post>)context.SourceValue; 

它實際上可能是

IEnumerable<Post> posts = context.SourceValue; 

回答

1

試圖讓死靈徽章。
如今這個任務可以通過使用ConstructUsing解決得更容易,函數指定的字段應該填充在提供的動作中,但是所有的通用字段都會去執行映射的ForMember。這種情況下的集合不需要任何額外的邏輯/映射配置。具有類型集合屬性的類也是如此。

cfg.CreateMap<Post, PostModel>() 
    .ConstructUsing(p => 
    { 
     switch (p.Type) 
     { 
      case LinkType.Html: return new LinkPostModel 
      { 
       Title = p.Description 
       // other specific fields 
      }; 
      case LinkType.Image: return new ImagePostModel 
      { 
       // other specific fields 
      }; 
     } 
     return null; 
    }) 
    .ForMember(x => x.PostId, m => m.MapFrom(p => p.Id)); 
cfg.CreateMap<PostList, PostListModel>();