AutoMapper映射列表时忽略目标多余属性避免被置空
问题解决步骤
1. 修正代码冗余与语法错误
首先移除重复定义的Person、PersonDTO、Info、InfoDTO类,避免编译冲突。同时修正映射配置中的语法错误:
public class PersonProfile : Profile { public PersonProfile() { CreateMap<PersonDTO, Person>() .ForMember(d => d.FirstName, opt => opt.MapFrom(src => src.FirstName)) .ForMember(d => d.LastName, opt => opt.MapFrom(src => src.LastName)) .ForMember(d => d.Information, opt => opt.ResolveUsing<PersonCollectionResolver>()); CreateMap<InfoDTO, Info>() .ForMember(d => d.info1, opt => opt.MapFrom(src => src.info1)) .ForMember(d => d.info2, opt => opt.MapFrom(src => src.info2)) .ForMember(d => d.info3, opt => opt.Ignore()); // 修正opt.opt为opt } }
2. 实现集合更新自定义解析器
AutoMapper默认会替换整个集合并创建新元素,导致原有info3值丢失。我们需要自定义解析器来逐个更新已有元素:
public class PersonCollectionResolver : IValueResolver<PersonDTO, Person, List<Info>> { private readonly IMapper _mapper; public PersonCollectionResolver(IMapper mapper) { _mapper = mapper; } public List<Info> Resolve(PersonDTO source, Person destination, List<Info> destMember, ResolutionContext context) { // 源集合为空时,保留目标原有集合 if (source.Information == null) return destMember; // 目标集合为空时,直接映射源集合生成新元素 if (destMember == null) return _mapper.Map<List<Info>>(source.Information); // 逐个更新对应位置的元素(假设列表顺序匹配) int minCount = Math.Min(source.Information.Count, destMember.Count); for (int i = 0; i < minCount; i++) { // 使用Map更新已有Info对象,info3会被忽略保留原值 _mapper.Map(source.Information[i], destMember[i]); } // 源集合有新增元素时,添加到目标集合 for (int i = minCount; i < source.Information.Count; i++) { destMember.Add(_mapper.Map<Info>(source.Information[i])); } // 如需删除目标集合中多余元素,可在此添加逻辑,此处默认保留 return destMember; } }
3. 注册解析器并验证
确保自定义解析器已注入DI容器(如果使用依赖注入),之后调用_mapper.Map(personDTOUpdated, person)时,Person.Information中的原有info3值将被保留,仅更新info1和info2。
关键说明
- 忽略
info3的配置确保单个元素映射时不会覆盖原有值; - 自定义解析器避免了集合被整体替换,实现了元素级的更新逻辑;
- 如果
Info类有唯一标识(如Id),可以修改解析器逻辑,根据标识匹配元素而非依赖顺序,提升可靠性。
内容的提问来源于stack exchange,提问作者Jim Buschman
相关产品推荐
相关产品推荐

