如何映射同类型列表属性?Category与CategoryDto映射场景
如何映射同类型的列表属性(比如嵌套分类列表)
嘿,我来帮你搞定这个同类型列表的映射问题!你需要把Category实体里的嵌套子分类列表(还有关联的产品列表)映射到对应的CategoryDto对吧?下面我会用两种实际项目里常用的方案来讲解,不管是小项目手动控制,还是中大型项目用工具简化代码都能覆盖到。
一、手动映射(适合小项目或需要精细控制的场景)
首先得补全你的CategoryDto(我默认你需要对应的嵌套子分类和产品列表属性,要是有调整你可以按需修改):
public class CategoryDto { public Guid Id { get; set; } public string CategoryName { get; set; } public Guid? ParentCategoryId { get; set; } public int? Level { get; set; } // 对应原始类的ChildrenCategory public IList<CategoryDto> ChildrenCategoryDto { get; } = new List<CategoryDto>(); // 对应原始类的Products,假设你有配套的ProductDto public IList<ProductDto> ProductsDto { get; } = new List<ProductDto>(); } // 配套的ProductDto示例 public class ProductDto { public Guid Id { get; set; } public string ProductName { get; set; } // 其他产品属性按需添加 }
因为是同类型的递归列表(子分类还是Category类型),我们需要写个递归的映射方法来处理整个嵌套树:
public static class CategoryMapper { // 单个Category转CategoryDto public static CategoryDto MapToDto(Category category) { if (category == null) return null; var dto = new CategoryDto { Id = category.Id, CategoryName = category.CategoryName, ParentCategoryId = category.ParentCategoryId, Level = category.Level }; // 递归映射子分类列表:每个子Category都转成CategoryDto foreach (var child in category.ChildrenCategory) { dto.ChildrenCategoryDto.Add(MapToDto(child)); } // 顺便处理Products列表到ProductDto的映射 foreach (var product in category.Products) { dto.ProductsDto.Add(MapProductToDto(product)); } return dto; } // 批量映射:把Category列表转成CategoryDto列表 public static List<CategoryDto> MapToDtoList(IList<Category> categories) { return categories?.Select(MapToDto).ToList() ?? new List<CategoryDto>(); } // 辅助方法:Product转ProductDto private static ProductDto MapProductToDto(Product product) { if (product == null) return null; return new ProductDto { Id = product.Id, ProductName = product.ProductName }; } }
这里的核心逻辑就是递归调用映射方法处理子分类,这样不管你的分类树有多少层,都能完整映射到Dto的嵌套列表里。
二、使用AutoMapper(适合中大型项目,减少重复代码)
如果你的项目比较大,手动写映射会很繁琐,AutoMapper这个工具能帮你自动处理递归映射,只需要配置一次规则就行。
步骤1:安装AutoMapper
通过NuGet包管理器安装:
Install-Package AutoMapper Install-Package AutoMapper.Extensions.Microsoft.DependencyInjection
步骤2:配置映射规则
创建一个映射配置类,告诉AutoMapper怎么把实体转成Dto:
public class MappingProfile : Profile { public MappingProfile() { // 配置Category到CategoryDto的映射 CreateMap<Category, CategoryDto>() // 显式指定子分类列表的映射(AutoMapper能自动识别递归,但显式写更清晰) .ForMember(dest => dest.ChildrenCategoryDto, opt => opt.MapFrom(src => src.ChildrenCategory)) // 配置Products到ProductsDto的映射 .ForMember(dest => dest.ProductsDto, opt => opt.MapFrom(src => src.Products)); // 配置Product到ProductDto的映射 CreateMap<Product, ProductDto>(); } }
步骤3:注册AutoMapper到依赖注入(ASP.NET Core项目)
在Program.cs里把AutoMapper加入服务容器:
builder.Services.AddAutoMapper(typeof(MappingProfile));
步骤4:实际使用映射
在需要的地方注入IMapper接口,直接调用映射方法就行:
public class CategoryService { private readonly IMapper _mapper; // 构造函数注入IMapper public CategoryService(IMapper mapper) { _mapper = mapper; } public CategoryDto GetCategoryById(Guid id) { // 假设从数据库获取Category实体 var category = FetchCategoryFromDatabase(id); // 单个实体转Dto var categoryDto = _mapper.Map<CategoryDto>(category); // 如果是列表的话,直接转列表 // var categoryDtos = _mapper.Map<List<CategoryDto>>(categoryList); return categoryDto; } // 模拟数据库查询方法 private Category FetchCategoryFromDatabase(Guid id) { // 这里写你的实际查询逻辑 return new Category(); } }
AutoMapper会自动识别递归关系,处理子分类列表的时候会自动复用已经配置好的Category到CategoryDto的规则,完全不用你手动写递归,非常省心!
小提示
- 如果你的Dto列表属性名称和实体的名称完全一致(比如实体是
ChildrenCategory,Dto也是ChildrenCategory),那AutoMapper可以自动匹配,不需要写ForMember配置。 - 手动映射的时候一定要注意空值判断,避免出现NullReferenceException,比如先检查
category是否为null再处理。 - 要是分类嵌套层级特别深,手动映射可能会有一点点性能开销,但一般业务场景下分类层级不会超过5层,所以基本没影响;AutoMapper内部做了优化,递归映射的表现很稳定。
内容的提问来源于stack exchange,提问作者Richard77
相关产品推荐
相关产品推荐

