2012-08-05 8 views
5

私はAutoMapperを実装し始めています。まず、すでに使用しているCastle.Windsorと統合することができました。今私は​​またはImagePostModelにマップしたいPostエンティティを持っています。AutoMapper列挙型に基づいた異なるタイプへのマップ?

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を実施する上でのポイントは次のように繰り返しコードを削除しているので、どのように私は共通のものをマッピングすることになっています:どちらも、これは私がこれまで持っているものであるPostModel

1)継承します

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)このマッピングが完了した後。だから、基本的に私は私が最初の記事リストをマッピングすることができます別のTypeConverter(?右)を、必要があると思い

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

:私はIEnumerable<Post>に以下のモデルをマッピングする必要があり、「親」のマッピングを、持っています、その後、私はこれを持っているが、それは一種の不格好な感じ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 = context.SourceValue; 

答えて

1

可能性があり

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


今日この作業は、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>(); 
関連する問題