2012-08-05 12 views
5

Zaczynam wdrażać AutoMapper, najpierw udało mi się zintegrować go z Castle.Windsor, którego już używam. Teraz mam jednostkę Post, którą chcę odwzorować na LinkPostModel lub ImagePostModel. Zarówno dziedziczą PostModelMapa AutoMapy do innego typu na podstawie wyliczenia?

1) To, co mam tak daleko:

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

Oczywiście punktem w realizacji AutoMapper jest usunięcie powtarzania kodu takiego, więc jak mam się odwzorować wspólną rzeczy przed dodaniem moje własne zasady (takie jak klauzula if-)

Idealnie chciałbym, żeby to było coś takiego:

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) Po zakończeniu tego mapowania. Mam „dominująca” mapping, gdzie potrzebne do mapowania IEnumerable<Post> następujący model:

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

Więc w zasadzie ja potrzebuję innego TypeConverter(prawda?), która pozwala mi na mapę listę posty pierwszy , a następnie utworzyć og:model

mam tego, ale czuje się trochę niezgrabne, czuję to mogło być lepiej:

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) Nie uruchomiłem jeszcze kodu, więc przychodzi mi na myśl inne pytanie i dlatego nie są silnie wpisywane odwzorowania w konwerterach?

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

gdzie może to być rzeczywiście

IEnumerable<Post> posts = context.SourceValue; 

Odpowiedz

1

Próbując dostać Necromancer odznaki.
W dzisiejszych czasach to zadanie można znacznie łatwiej rozwiązać, używając pól o określonych funkcjach, które powinny zostać wypełnione w podanej akcji, ale wszystkie wspólne pola zostaną przeniesione do ForMember wykonanie odwzorowania. Kolekcje w tym przypadku nie wymagają żadnych dodatkowych konfiguracji logicznych/mapujących. Klasy posiadające również właściwość kolekcji typów.

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>(); 
Powiązane problemy