使用automapper从两个项目映射

时间:2012-08-21 09:24:03

标签: c# automapper

在我的数据层中,我有一个存储库,可以返回这样的项目列表:

new List<Item> {
    new Item { Title = "Something", DetailId = 500 },
    new Item { Title = "Whatever", DetailId = 501 },
}

存储库有另一种方法,可以在给定项目详细信息ID时返回这些项目的详细信息:

// repository.GetDetail(500) would return something like:
new ItemDetail {
    Id = 500,
    Size = "Large"        
}

现在,在我的服务层中,我想将上面的列表映射成如下:

new List<ServiceItem> {
    new ServiceItem { Title = "Something", Size = "Large" },
    new ServiceItem { Title = "Whatever", Size = "Medium" },
}

请注意,我需要来自列表中的对象(在本例中为Title)和详细对象的属性。有没有什么好的方法可以使用AutoMapper进行映射?

我考虑过创建一个依赖于我的存储库实例的配置文件,然后让AutoMapper执行详细请求,但让AutoMapper获取新数据有点麻烦吗?

是否有一种干净的方式从两个对象映射到一个?

3 个答案:

答案 0 :(得分:4)

一种可能性是将Item和ItemDetail对象包装在元组中,并根据该元组定义Map。映射代码看起来像这样。

Mapper.CreateMap<Tuple<Item, ItemDetail>, ServiceItem>()
    .ForMember(d => d.Title, opt => opt.MapFrom(s => s.Item1.Title))
    .ForMember(d => d.Size, opt => opt.MapFrom(s => s.Item2.Size));

您必须自己加入正确的Item和ItemDetail。如果您希望Automapper也将Item与正确的ItemDetail匹配,则需要更改映射,以便在解析Size时,Automapper执行查找并返回匹配的大小。代码看起来像这样。

Mapper.CreateMap<Item, ServiceItem>()
    .ForMember(d => d.Size, opt => opt.MapFrom(s => itemDetails.Where(x => s.DetailId == x.Id).First().Size));

此映射使用Automapper的自动功能将Item.Title映射到ServiceItem.Title。映射使用名为itemDetails的IEnumerable来查找匹配项,但应该可以用数据库调用替换它。现在,由于我认为这种类型的查找不是Autmapper设计的,因此对于大量项目来说,性能可能不是那么好。那将是值得测试的东西。

答案 1 :(得分:2)

此博客介绍了执行此操作的方法:http://consultingblogs.emc.com/owainwragg/archive/2010/12/22/automapper-mapping-from-multiple-objects.aspx。它为每个输入对象进行一次Map()调用,但至少将其包装在一个帮助器中。

答案 2 :(得分:0)

使用ValueInjecter而不是AutoMapper,它很容易在两者之间切换,而ValueInjecter支持从多个来源开始注入值。

serviceItem.InjectFrom(item);
serviceItem.InjectFrom(itemDetail);

作为奖励,您不必像使用AutoMapper一样进行所有静态映射