4

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

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 获取新数据感觉有点混乱?

有没有一种干净的方法可以将两个对象映射为一个对象?

4

3 回答 3

4

一种可能性是将您的 Item 和 ItemDetail 对象包装在一个 Tuple 中,并根据该 Tuple 定义您的 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 执行查找并返回匹配的 Size。代码看起来像这样。

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 的设计目的是进行这种类型的查找,因此对于大量项目而言,性能可能不是那么好。那将是要测试的东西。

于 2012-08-21T20:23:32.720 回答
2

这个博客描述了一种方法来做到这一点:http ://consultingblogs.emc.com/owainwragg/archive/2010/12/22/automapper-mapping-from-multiple-objects.aspx 。它对每个输入对象进行一次 Map() 调用,但至少将其包装在一个助手中。

于 2012-08-21T12:21:12.767 回答
0

使用 ValueInjecter 而不是 AutoMapper,它可以在两者之间轻松切换,并且 ValueInjecter 支持开箱即用地从多个来源注入值。

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

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

于 2012-08-21T20:26:43.863 回答