AutoMapper是否基于枚举映射到其他类型? [英] AutoMapper Map to different type based on an enum?

查看:82
本文介绍了AutoMapper是否基于枚举映射到其他类型?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我开始实现 AutoMapper ,首先我设法将其与Castle.Windsor集成在一起我已经在用了.现在,我有一个Post实体,我想将其映射到LinkPostModelImagePostModel.两者都继承自PostModel

I'm starting to implement AutoMapper, first I managed to integrate it with Castle.Windsor, which I'm already using. Now I have a Post entity which I want to map to either a LinkPostModel or an ImagePostModel. Both inherit from PostModel

1)这是我到目前为止的内容:

1) This is what I have so far:

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子句)

Obviously the point in implementing AutoMapper is removing repeat code like this, so how am I supposed to map the common stuff, before adding my custom rules (such as the if-clause)

理想情况下,我希望它类似于:

Ideally I'd want this to be something like:

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>以下模型:

2) After this mapping is complete. I have a "parent" mapping, where I need to map an IEnumerable<Post> the following model:

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

So basically I'd need another TypeConverter (right?), which allows me to map the posts list first, and then create the og:model

我有这个,但感觉有点笨拙,我觉得可能会更好:

I have this, but it feels kind of clunky, I feel it could be better:

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)我实际上还没有运行代码,所以又想到了一个问题,那就是为什么转换器中的映射类型不是很强?

3) I didn't actually run the code yet, so another question comes to mind, and that is why aren't mappings strongly typed in converters?

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

实际上可能在哪里

IEnumerable<Post> posts = context.SourceValue;

推荐答案

试图获取死灵法师徽章.
如今,通过使用ConstructUsing函数可以轻松地解决此任务,应该在提供的操作中填充指定字段,但是所有公共字段都将转到映射的ForMember执行中.在这种情况下,集合不需要任何其他逻辑/映射配置.具有属性collection类型的类.

Trying to get Necromancer badge.
Nowadays this task can be solved much easier with using ConstructUsing function specifc fields should be filled in the provided action, but all the common fields will go to ForMember execution of the mapping. Collections in this case doesn't requires any additional logic/mapping configurations. Classes that has a property of type collection as well.

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是否基于枚举映射到其他类型?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆