You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用Automapper实现带条件的对象列表映射(含ProductType示例)

使用AutoMapper实现带条件的ProductType列表映射

针对你的问题,我来一步步讲解如何用AutoMapper实现带条件的对象列表映射,覆盖单个对象的字段条件处理和列表内父-子关系关联两种常见场景:

1. 先定义API视图模型

首先创建和领域对象对应的视图模型,你可以根据API的实际需求调整字段(比如把int类型的Active转成更符合API习惯的bool):

public class ProductTypeViewModel
{
    public int Id { get; set; }
    public string Name { get; set; }
    public string Description { get; set; }
    public int ParentProductTypeId { get; set; }
    public bool IsActive { get; set; }
    public DateTime UpdatedOnUtc { get; set; }
}

另外提一句:你的领域对象里字段名拼写错了——PerentProductTypeId应该是ParentProductTypeId,建议修正这个拼写,避免后续出现不必要的bug。

2. 配置AutoMapper映射规则

创建一个继承自Profile的配置类,在这里定义核心的映射逻辑,包括你需要的条件判断:

场景1:单个对象的条件字段映射

如果你的需求是针对单个ProductType,根据业务规则判断它是否是某个父类型的子集,再设置对应的ParentProductTypeId,可以用ForMember结合MapFrom或ResolveUsing实现:

public class ProductTypeProfile : Profile
{
    public ProductTypeProfile()
    {
        CreateMap<ProductType, ProductTypeViewModel>()
            // 常规字段映射:把int类型的Active转成bool
            .ForMember(dest => dest.IsActive, opt => opt.MapFrom(src => src.Active == 1))
            // 处理ParentProductTypeId的条件逻辑
            .ForMember(dest => dest.ParentProductTypeId, opt => 
            {
                // 示例:如果产品名称包含"T恤",则设置父ID为休闲服饰的ID(假设休闲服饰ID是1)
                opt.MapFrom(src => src.Name.Contains("T恤") ? 1 : src.PerentProductTypeId);
                
                // 如果你的条件逻辑需要依赖外部数据(比如从数据库查父类型),可以用ResolveUsing
                // opt.ResolveUsing((src, dest, _, context) => 
                // {
                //     // 这里可以通过上下文注入服务,或者传递额外数据
                //     var parentService = context.GetService<IParentProductTypeService>();
                //     return parentService.GetParentIdForSubset(src) ?? src.PerentProductTypeId;
                // });
            });
    }
}

场景2:列表内的父-子关系映射

如果你的需求是在映射整个ProductType列表时,自动识别列表内的父-子关系,确保子类型的ParentProductTypeId正确对应父类型的ID,可以通过AutoMapper的上下文传递整个列表,再在映射逻辑中做判断:

public class ProductTypeProfile : Profile
{
    public ProductTypeProfile()
    {
        CreateMap<ProductType, ProductTypeViewModel>()
            .ForMember(dest => dest.IsActive, opt => opt.MapFrom(src => src.Active == 1))
            .ForMember(dest => dest.ParentProductTypeId, opt => 
            {
                opt.ResolveUsing((src, dest, _, context) => 
                {
                    // 从上下文获取整个ProductType列表
                    var allProductTypes = context.Items["AllProductTypes"] as IEnumerable<ProductType>;
                    if (allProductTypes == null) return src.PerentProductTypeId;

                    // 自定义子集判断逻辑:判断当前产品是否是列表中某个父类型的子集
                    var parentType = allProductTypes.FirstOrDefault(pt => IsSubsetOf(src, pt));
                    return parentType?.Id ?? src.PerentProductTypeId;
                });
            });
    }

    // 封装子集判断的业务逻辑
    private bool IsSubsetOf(ProductType child, ProductType parent)
    {
        // 示例规则:根据名称判断父子关系
        if (parent.Name == "休闲服饰" && (child.Name == "T恤" || child.Name == "牛仔裤"))
        {
            return true;
        }
        if (parent.Name == "办公文具" && (child.Name == "笔记本" || child.Name == "钢笔"))
        {
            return true;
        }
        return false;
    }
}

3. 执行映射(以ASP.NET Core为例)

注册AutoMapper

在Program.cs中注册AutoMapper服务:

builder.Services.AddAutoMapper(typeof(ProductTypeProfile));

在控制器中使用

通过依赖注入获取IMapper实例,执行映射时把整个列表传入上下文:

public class ProductTypeController : ControllerBase
{
    private readonly IMapper _mapper;
    private readonly ApplicationDbContext _dbContext;

    public ProductTypeController(IMapper mapper, ApplicationDbContext dbContext)
    {
        _mapper = mapper;
        _dbContext = dbContext;
    }

    [HttpGet]
    public async Task<ActionResult<List<ProductTypeViewModel>>> GetAll()
    {
        var productTypes = await _dbContext.ProductTypes.ToListAsync();
        
        // 传递整个列表到AutoMapper上下文,供映射逻辑使用
        var viewModels = _mapper.Map<List<ProductTypeViewModel>>(productTypes, opt => 
        {
            opt.Items["AllProductTypes"] = productTypes;
        });
        
        return Ok(viewModels);
    }
}

小提示

  • 如果你的子集判断逻辑很复杂,建议把它封装到单独的业务服务类中,不要直接写在Profile里,保持映射配置的简洁性。
  • 如果存在顶级分类(没有父类型),记得处理ParentProductTypeId的空值/默认值情况,避免视图模型返回无效数据。

内容的提问来源于stack exchange,提问作者AshanMG

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.26 08:41:20