2012-08-05 35 views
5

Tôi bắt đầu triển khai AutoMapper, trước tiên tôi đã tích hợp nó với Castle.Windsor, mà tôi đã sử dụng. Bây giờ tôi có một thực thể Post mà tôi muốn ánh xạ tới LinkPostModel hoặc ImagePostModel. Cả hai thừa hưởng từ PostModelAutoMapper Bản đồ với loại khác nhau dựa trên enum?

1) Đây là những gì tôi có cho đến nay:

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

Rõ ràng điểm trong việc thực hiện AutoMapper là loại bỏ mã lặp lại như thế này, vậy làm thế nào mà tôi có để lập bản đồ các công cụ phổ biến , trước khi thêm quy tắc tùy chỉnh của tôi (như mệnh đề if-)

Lý tưởng nhất là tôi muốn điều này để có cái gì đó như:

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) Sau khi ánh xạ này hoàn tất. Tôi có một "cha mẹ" lập bản đồ, nơi mà tôi cần để ánh xạ một IEnumerable<Post> mô hình sau:

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

Vì vậy, về cơ bản tôi muốn cần một TypeConverter(phải không?), cho phép tôi để lập bản đồ danh sách bài đăng đầu tiên , và sau đó tạo ra các og:model

tôi có điều này, nhưng nó cảm thấy loại clunky, tôi cảm thấy nó có thể là tốt hơn:

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) Tôi chưa thực sự chạy mã, vì vậy một câu hỏi khác xuất hiện trong đầu, và đó là lý do tại sao các ánh xạ không được đánh máy mạnh trong bộ chuyển đổi?

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

nơi nó thực sự có thể là

IEnumerable<Post> posts = context.SourceValue; 

Trả lời

1

Đang cố gắng để có được Necromancer huy hiệu.
Ngày nay, nhiệm vụ này có thể được giải quyết dễ dàng hơn khi sử dụng các trường đặc biệt chức năng ConstructUsing trong hành động được cung cấp, nhưng tất cả các trường phổ biến sẽ thực hiện ánh xạ ForMember. Các bộ sưu tập trong trường hợp này không yêu cầu bất kỳ cấu hình logic/ánh xạ bổ sung nào. Các lớp có thuộc tính của bộ sưu tập kiểu là tốt.

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>(); 
Các vấn đề liên quan