2012-08-05 7 views
5

Ich beginne zu implementieren AutoMapper, zuerst habe ich es mit Castle.Windsor zu integrieren, die ich bereits verwende. Jetzt habe ich eine Post Einheit, die ich entweder einer LinkPostModel oder einer ImagePostModel zuordnen möchte. Beide erben von PostModelAutoMapper Map zu verschiedenen Typen basierend auf einer Enum?

1) Dies ist, was habe ich bisher:

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

Offensichtlich ist der Punkt AutoMapper bei der Implementierung wiederholen Codes wie folgt zu entfernen, so wie sollte ich die gemeinsame Sachen kartieren , bevor meine benutzerdefinierten Regeln (wie die if-Klausel)

im Idealfall würde ich will, dass diese etwas sein, wie das Hinzufügen von:

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) Nachdem diese Zuordnung abgeschlossen ist. Ich habe eine „Eltern“ Mapping, wo Ich brauche eine IEnumerable<Post> das folgende Modell zur Karte:

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

Also im Grunde würde ich brauche einen anderen TypeConverter(rechts?), die mir die Beiträge Liste Karte ermöglicht es zuerst und dann auf die diese ich habe og:model

schaffen, aber es fühlt sich irgendwie klobig, halte ich es besser sein könnte:

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) Ich habe den Code noch nicht ausgeführt, daher fällt mir eine andere Frage ein, und deshalb werden Mappings in Konvertern nicht stark typisiert?

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

wo es tatsächlich

IEnumerable<Post> posts = context.SourceValue; 

Antwort

1

Versuch Necromancer Abzeichen zu bekommen sein könnte.
Heutzutage kann diese Aufgabe viel einfacher gelöst werden mit ConstructUsing Funktion specifc Felder sollten in der bereitgestellten Aktion ausgefüllt werden, aber alle gängigen Felder gehen auf ForMember Ausführung des Mappings. Collections erfordert in diesem Fall keine zusätzlichen Logik-/Mapping-Konfigurationen. Klassen, die auch eine Eigenschaft der Typsammlung besitzen.

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>(); 
Verwandte Themen