我对AutoMapper有些新意,并希望将POCO-ish对象映射到可能更复杂的DTO,后者试图表示Google Books API's Volume资源:
Book.cs
public class Book
{
public string Isbn10 { get; set; }
public string Isbn13 { get; set; }
public string Title { get; set; }
public string Author { get; set; }
public string Publisher { get; set; }
public DateTime Publication { get; set; }
public int Pages { get; set; }
public string Description { get; set; }
public bool InStock { get; set; }
}
BookDto.cs
public class BookDto
{
public string Kind { get; set; }
public string Id { get; set; }
public VolumeInfo VolumeInfo { get; set; }
}
public class VolumeInfo
{
public string Title { get; set; }
public List<string> Authors { get; set; }
public string Publisher { get; set; }
public string PublishedDate { get; set; }
public string Description { get; set; }
public int PageCount { get; set; }
public List<IndustryIdentifier> IndustryIdentifiers { get; set; }
}
public class IndustryIdentifier
{
public string Type { get; set; }
public string Identifier { get; set; }
}
因此,根据documentation ,我们可以简单地展平嵌套类型:
AutoMapperConfigurator.cs
public static class AutoMapperConfigurator
{
public static void Configure()
{
Mapper.CreateMap<Book, BookDto>()
.ForMember(dto => dto.Id, options => options.Ignore())
.ForMember(dto => dto.Kind, options => options.Ignore())
.ForMember(dto => dto.VolumeInfo.Title, options => options.MapFrom(book => book.Title))
.ForMember(dto => dto.VolumeInfo.Authors, options => options.MapFrom(book => book.Author.ToArray()))
.ForMember(dto => dto.VolumeInfo.Publisher, options => options.MapFrom(book => book.Publisher))
.ForMember(dto => dto.VolumeInfo.PublishedDate, options => options.MapFrom(book => book.Publication))
.ForMember(dto => dto.VolumeInfo.Description, options => options.MapFrom(book => book.Description))
.ForMember(dto => dto.VolumeInfo.PageCount, options => options.MapFrom(book => book.Pages))
;
}
}
但遗憾的是,在运行Mapper.AssertConfigurationIsValid()
测试时,我收到以下错误:
System.ArgumentException:Expression'dto =&gt; dto.VolumeInfo.Title” 必须解析为顶级成员而不是任何子对象 属性。在子类型或AfterMap上使用自定义解析程序 相反的选择。参数名称:lambdaExpression
所以现在尝试使用AfterMap的建议:
public static class AutoMapperConfigurator
{
public static void Configure()
{
Mapper.CreateMap<Book, BookDto>()
.ForMember(dto => dto.Id, options => options.Ignore())
.ForMember(dto => dto.Kind, options => options.Ignore())
.AfterMap((book, bookDto) => bookDto.VolumeInfo = new VolumeInfo
{
Title = book.Title,
Authors = new List<string>(){ book.Author },
Publisher = book.Publisher,
PublishedDate = book.Publication.ToShortDateString(),
Description = book.Description,
PageCount = book.Pages
});
}
}
再次运行测试时,我现在收到此消息:
找到未映射的成员。查看下面的类型和成员。添加一个 自定义映射表达式,忽略,添加自定义解析程序或修改 源/目的地类型书 - &gt; BookDto(目的地成员列表) Dotnet.Samples.AutoMapper.Book - &gt; Dotnet.Samples.AutoMapper.BookDto (目标成员列表)VolumeInfo
我应该在嵌套类之间创建其他映射吗?我们将非常感谢任何指导,非常感谢。
答案 0 :(得分:29)
在使用.ForMember和VolumnInfo映射的内部映射之前,我做了类似的事情:
public static class AutoMapperConfigurator
{
public static void Configure()
{
Mapper.CreateMap<Book, VolumeInfo>()
.ForMember(dto => dto.Authors, options => options.MapFrom(book => book.Author.Split(',')))
.ForMember(dto => dto.PublishedDate, options => options.MapFrom(book => book.Publication))
.ForMember(dto => dto.PageCount, options => options.MapFrom(book => book.Pages))
.ForMember(dto => dto.IndustryIdentifiers, options => options.Ignore());
Mapper.CreateMap<Book, BookDto>()
.ForMember(dto => dto.Id, options => options.Ignore())
.ForMember(dto => dto.Kind, options => options.Ignore())
.ForMember(dto => dto.VolumeInfo, options => options.MapFrom(book => Mapper.Map<Book, VolumeInfo>(book)));
}
}
以下是一些验证功能的单元测试:
[TestFixture]
public class MappingTests
{
[Test]
public void AutoMapper_Configuration_IsValid()
{
AutoMapperConfigurator.Configure();
Mapper.AssertConfigurationIsValid();
}
[Test]
public void AutoMapper_MapsAsExpected()
{
AutoMapperConfigurator.Configure();
Mapper.AssertConfigurationIsValid();
var book = new Book
{
Author = "Castle,Rocks",
Description = "Awesome TV",
InStock = true,
Isbn10 = "0123456789",
Isbn13 = "0123456789012",
Pages = 321321,
Publication = new DateTime(2012, 11, 01),
Publisher = "Unknown",
Title = "Why I Rock"
};
var dto = Mapper.Map<Book, BookDto>(book);
Assert.That(dto.Id, Is.Null);
Assert.That(dto.Kind, Is.Null);
Assert.That(dto.VolumeInfo, Is.Not.Null);
Assert.That(dto.VolumeInfo.Authors, Is.Not.Null);
Assert.That(dto.VolumeInfo.Authors.Count, Is.EqualTo(2));
Assert.That(dto.VolumeInfo.Authors[0], Is.EqualTo("Castle"));
Assert.That(dto.VolumeInfo.Authors[1], Is.EqualTo("Rocks"));
Assert.That(dto.VolumeInfo.Description, Is.EqualTo("Awesome TV"));
Assert.That(dto.VolumeInfo.IndustryIdentifiers, Is.Null);
Assert.That(dto.VolumeInfo.PageCount, Is.EqualTo(321321));
Assert.That(dto.VolumeInfo.PublishedDate, Is.EqualTo(new DateTime(2012, 11, 01).ToString()));
Assert.That(dto.VolumeInfo.Publisher, Is.EqualTo("Unknown"));
Assert.That(dto.VolumeInfo.Title, Is.EqualTo("Why I Rock"));
}
}