如何使用AutoMapper创建复杂的映射?

时间:2018-03-02 00:53:00

标签: c# asp.net-mvc asp.net-mvc-5 automapper automapper-6

我有以下实体模型

public class Blog 
{
    public int Id { get; set;}
    public string Title { get; set; }
    public string Body { get; set; }

    [ForeignKey("Category")]
    public int? CategoryId { get; set; }
    public virtual Category Category { get; set; }
    public virtual ICollection<Comment> Comments { get; set; }
}

public class Category
{
    public int Id { get; set;}

    public string Name { get; set; }
}

public class Comment
{
    public int Id { get; set;}

    public string Title { get; set; }
    public string Body { get; set; }
    [ForeignKey("Blog")]
    public int BlogId { get; set; }
    public virtual Blog Blog { get; set; }
}

然后我有以下视图模型,其中我想告诉AutoMapper将Blog对象映射到BlogViewModel通知CategoryName属性需要来自{{1并且Blog.Category.Name中的每个Comment都需要使用有机约定转换为Blog.Comments

我目前在运行时使用反射为任何实现CommentViewModel接口的类设置映射。请通过ICustomMap方法阅读代码中的注释。

Transfer(IMapper mapper)

最后这是我的public class BlogViewModel : ICustomMapFrom { public int Id { get; set; } public string Title { get; set; } public string Body { get; set; } public string MyCatName { get; set; } public IEnumerable<CommentViewModel> Comments { get; set; } // **IMPORTANT NOTE** // This method is called using reflection when the on Application_Start() method. // If IMapper is the wrong Interface to pass, I can change // the implementation of ICustomMap // I assumed that `IMapper` is what is needed to add configuration at runtime. public void Transfer(IConfigurationProvider config) { // How to I do the custom mapping for my MyCatName and Comments? // I need to use the config to create the complex mapping // AutoMapper.Mapper.Map(typeof(Blog), typeof(BlogViewModel)); } }

CommentViewModel

如何告诉AutoMapper如何映射CategoryName和评论?

更新

以下是我将如何创建映射。我会有以下3个接口

public class CommentViewModel : IMapFrom<Comment>
{
    public int Id { get; set; }
    public string Title { get; set; }
    public string Body { get; set; }
}

然后在Global.cs文件中

我会在启动时执行public interface IMap { } public interface IMapFrom<T> : IMap { } public interface ICustomMapFrom : IMap { void Map(IConfigurationProvider config); } 方法。基本上这个方法将扫描程序集并注册我想要使用接口注册的类。

Run

1 个答案:

答案 0 :(得分:0)

我写了一个NUnit测试,用你的类设置AutoMapper。 AutoMapper支持开箱即用CategoryName的映射。

[TestFixture]
public class TestClass
{
    [Test]
    public void Test1()
    {
        var config = new MapperConfiguration(cfg =>
        {
            cfg.CreateMap<Blog, BlogViewModel>();
        });

        config.AssertConfigurationIsValid();

        var blog = new Blog()
        {
            Body = "Blog body",
            Category = new Category { Name = "My Category" },
            Comments = new List<Comment>() {
                new Comment { Body = "Comment body 1" },
                new Comment { Body = "Comment body 2" }
            }
        };

        var mapper = config.CreateMapper();
        var result = mapper.Map<Blog, BlogViewModel>(blog);

        Assert.AreEqual(blog.Body, "Blog body");
        Assert.AreEqual(blog.Category.Name, result.CategoryName);
        List<CommentViewModel> comments = result.Comments.ToList();
        Assert.That(comments.Any(c => c.Body == "Comment body 1"));
        Assert.That(comments.Any(c => c.Body == "Comment body 2"));
    }
}