2012-08-05 118 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>();