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ą PostModel
Mapa 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;