如何在Automapper中将列表中的条件对象展平

8
我有一个包含Product列表的Item,使用AutoMapper将其映射到相应的ViewModel对象中。
在我的MVC项目中,我有一个操作方法,用于显示一个带有选择的ProductItem。为此,我有一个名为ItemDetailsViewModelViewModel,其中包含平整的Item对象、ProductViewModel列表和平整的选择的Product
我遇到的困难是如何最好地显示这个平整的选定Product
可以将它想象成eBay,您可以选择多个变化,例如按颜色。对于我来说,多个变化就是Products。当用户选择Product时,我希望返回ItemDetails,即ItemProducts列表和选定的Product
我想知道最好的方法是什么?目前,我的方法是将一个Item映射到一个ItemDetailsViewModel,选择所需的ProductViewModel,然后具体地将ProductViewModel的每个属性映射回ItemDetailsViewModel上。此外,由于ItemProduct具有相同命名的属性,最后一行映射产品会覆盖Item的ID和代码。
您对如何配置映射有什么建议吗?
我省略了我已经完成的映射,因为它基本上是直接的一对一映射,除了将选择的ProductViewModel映射回ItemDetailsViewModel
Mapper.CreateMap<Item, ItemViewModel>()
    .ReverseMap();

Mapper.CreateMap<ProductViewModel, ItemDetailsViewModel>()
    .ForMember(d => d.ProductId, o => o.MapFrom(s => s.Id))
    .ForMember(d => d.ProductCode, o => o.MapFrom(s => s.Code));

public class Item
{
    public int Id { get; set; }
    public string Code { get; set; }
    public IList<Product> Products { get; set; }
}

public class Product
{
    public int Id { get; set; }
    public string Code { get; set; }
}

public class ItemViewModel
{
    public int Id { get; set; }
    public string Code { get; set; }

    public IList<ProductViewModel> Products { get; set; }
}

public class ItemDetailsViewModel : ItemViewModel
{
    public int ProductId;
    public string ProductCode;
}

public class ProductViewModel
{
    public int Id { get; set; }
    public string Code { get; set; }
}

行动

public ActionResult ItemDetails()
{
    var item = new Item
    {
        Id = 1,
        Code = "Item1",
        Products = new List<Product>()
        {
            new Product { Id = 1, Code = "Product1" },
            new Product { Id = 2, Code = "Product2" },
            new Product { Id = 3, Code = "Product3" },
        }
    };

    var productCode = "Product2";
    var itemDetailsViewModel = Mapper.Map<ItemDetailsViewModel>(item);

    if (itemDetailsViewModel.Products != null && itemDetailsViewModel.Products.Count > 0)
    {
        ProductViewModel productViewModel = null;
        if (!String.IsNullOrEmpty(productCode))
            productViewModel = itemViewModel.Products.FirstOrDefault(e => e.Code.Equals(productCode, StringComparison.OrdinalIgnoreCase));

        if (productViewModel == null)
            productViewModel = itemViewModel.Products[0];

        Mapper.Map<ProductViewModel, ItemDetailsViewModel>(productViewModel, itemDetailsViewModel);
    }
}
1个回答

0
一个解决方案是在从ProductViewModelItemDetailsViewModel的映射中忽略ItemDetailsViewModel中的属性:
Mapper.CreateMap<ProductViewModel, ItemDetailsViewModel>()
    .ForMember(d => d.Id, opt => opt.Ignore())
    .ForMember(d => d.Code, opt => opt.Ignore())
    .ForMember(d => d.ProductId, o => o.MapFrom(s => s.Id))
    .ForMember(d => d.ProductCode, o => o.MapFrom(s => s.Code));

您可以查看此答案,了解忽略目标类型中不存在的属性的扩展方法:https://dev59.com/3nNA5IYBdhLWcg3wdthd#6280647 - Marshall777
1
@Marshall777:不确定这是否适用于此情况 - 在这种情况下,属性确实存在于目标类型上,这就是问题所在。 - Andrew Whitaker
我会试一下。有什么建议可以改进吗?看起来我正在编写/维护很多“这个到那个”的代码。也许这是由于我的实现方式所必须的。 - David
在我的经验中,这在使用视图模型时是必须的。不过我会继续思考替代方案。 - Andrew Whitaker

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接