基于AutoMapper映射到不同类型的枚举?(AutoMapper Map to differen

2019-07-30 19:24发布

我开始实行AutoMapper ,首先我设法将其与Castle.Windsor,这我已经使用整合。 现在我有一个Post ,我想映射到一个实体LinkPostModelImagePostModel 。 无论是从继承PostModel

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)该映射完成之后。 我有一个“父”的映射,其中,I需要映射一个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;

Answer 1:

试图让死灵徽章。
如今这个任务是可以解决的使用更容易ConstructUsing功能specifc字段应该在所提供的行动来填充,但所有的公共字段会去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>();


文章来源: AutoMapper Map to different type based on an enum?
标签: c# AutoMapper