AutoMapper实现平面对象属性映射为嵌套TargetObjectImage集合的方法咨询
AutoMapper 实现扁平化属性转嵌套集合(UNPIVOT)的可行方案
方案1:硬编码固定属性映射(适合ImageUri数量少且固定的场景)
直接在现有映射配置基础上补充Images属性的映射规则,手动枚举所有ImageUri属性,过滤空值后构造TargetObjectImage集合:
public class SourceObjectProfile : Profile { public SourceObjectProfile() { CreateMap<SourceObject, TargetObject>() // Code和Name属性名称完全一致时可以省略MapFrom配置,AutoMapper会默认按名称自动匹配 .ForMember(o => o.Images, opt => opt.MapFrom(src => new List<TargetObjectImage> { new TargetObjectImage{ Name = "Image1", ImageUri = src.ImageUri1 }, new TargetObjectImage{ Name = "Image2", ImageUri = src.ImageUri2 }, new TargetObjectImage{ Name = "Image3", ImageUri = src.ImageUri3 } // 后续新增图片属性在此处追加即可 } // 过滤Uri为空的无效项 .Where(img => !string.IsNullOrEmpty(img.ImageUri)) .ToList() )); } }
该方案逻辑直观无额外性能开销,适合属性数量固定且不多的业务场景。
方案2:反射动态获取属性(适合ImageUri数量多、后续可能新增的场景)
如果后续会不断新增ImageUri4、ImageUri5这类属性,可以用反射批量读取所有匹配命名规则的属性,避免每次新增都要修改映射代码:
public class SourceObjectProfile : Profile { public SourceObjectProfile() { CreateMap<SourceObject, TargetObject>() .ForMember(o => o.Images, opt => opt.MapFrom(src => src.GetType().GetProperties() // 筛选所有名称以ImageUri开头的字符串类型公共属性 .Where(p => p.Name.StartsWith("ImageUri") && p.PropertyType == typeof(string)) .Select(p => new { ImageName = "Image" + p.Name.Replace("ImageUri", string.Empty), Uri = p.GetValue(src)?.ToString() }) .Where(item => !string.IsNullOrEmpty(item.Uri)) .Select(item => new TargetObjectImage { Name = item.ImageName, ImageUri = item.Uri }) .ToList() )); } }
该方案可扩展性强,新增ImageUri开头的属性不需要修改映射配置,可自动适配。
优化技巧
- 同名属性的默认映射不需要手动写
ForMember配置,可大幅简化映射代码。 - 如果需要复用这个UNPIVOT逻辑到其他相似类型的映射,可以封装为AutoMapper的自定义值解析器(
IValueResolver),避免重复编码。
内容的提问来源于stack exchange,提问作者Cowa
相关产品推荐
相关产品推荐

