AutoMapper如何基于多源成员设置目标成员?状态映射为空排查
问题:AutoMapper映射Product到ViewProductDto时State始终为null
代码定义
ProductState类
public class ProductState { public static ProductState OutOfService => new(1, "Out of Service", "bg-secondary"); public static ProductState InService => new(2, "In Service", "bg-sucess"); public static ProductState Repair => new(3, "Repair","bg-dark"); public static ProductState Damaged => new(4, "Damaged","bg-warning text-dark"); public static ProductState Scrapped => new(5, "Scrapped", "badge-danger"); public static ProductState CheckedOut => new(6, "Checked Out", "bg-primary"); public ProductState (int id, string name, string css) { Id = id; Name = name; CSS = css; } public int Id { get; set; } public string Name { get; set; } public string CSS { get; set; } }
ViewProductDto类
public class ViewProductDto : BaseProductDto, IProductPartialDto { public ProductState State { get; set; } }
Product实体类
public class Product { public bool? IsDamaged { get; set; } public bool? IsScrapped { get; set; } public DateTime? WhenScrapped {get;set;} public List<InOut> Inout {get;set;} }
AutoMapper注册(Startup.cs)
services.AddAutoMapper(config => { config.AddProfile(new ViewProductMapper()); }, AppDomain.CurrentDomain.GetAssemblies());
AutoMapper配置文件ViewProductMapper
public class ViewProductMapper : Profile { public ViewProductMapper() { CreateMap<Product, ViewProductDto>() .ForMember(dest => dest.State, cfg => cfg.MapFrom(o=> MapProductState(o))) } private ProductState MapProductState(Product eqp) { if ((eqp.IsBeingScrapped.HasValue && eqp.IsBeingScrapped.Value) || eqp.ScrappedWhen.HasValue) { return ProductState.Scrapped; } else if ((eqp.IsDamage.HasValue && eqp.IsDamage.Value) && !((eqp.IsBeingScrapped.HasValue && eqp.IsBeingScrapped.Value) || eqp.ScrappedWhen.HasValue)) { return ProductState.Damaged; } else if (eqp.Inout != null && eqp.Inout.Any(a => a.Out)) { return ProductState.CheckedOut; } else { return ProductState.InService; } } }
执行映射代码
_mapper.Map<List<Product>, List<ViewDto>>(products)
问题原因及修复方案
1. 属性名称不匹配(核心问题)
MapProductState方法中使用的属性名称与Product实体定义完全不符:
- 实体中是
IsDamaged,方法里写的是IsDamage(缺失末尾字母d) - 实体中是
IsScrapped,方法里写的是IsBeingScrapped - 实体中是
WhenScrapped,方法里写的是ScrappedWhen
这些错误会导致条件判断逻辑失效,甚至运行时抛出异常,最终AutoMapper无法正确赋值State。
修复后的映射方法:
private ProductState MapProductState(Product eqp) { if ((eqp.IsScrapped.HasValue && eqp.IsScrapped.Value) || eqp.WhenScrapped.HasValue) { return ProductState.Scrapped; } else if ((eqp.IsDamaged.HasValue && eqp.IsDamaged.Value) && !((eqp.IsScrapped.HasValue && eqp.IsScrapped.Value) || eqp.WhenScrapped.HasValue)) { return ProductState.Damaged; } else if (eqp.Inout != null && eqp.Inout.Any(a => a.Out)) { return ProductState.CheckedOut; } else { return ProductState.InService; } }
2. 映射目标类型笔误
执行映射时写的是List<ViewDto>,但实际DTO类型是ViewProductDto,类型不匹配会导致映射逻辑无法正确应用到目标属性。
修复后的映射调用:
_mapper.Map<List<Product>, List<ViewProductDto>>(products)
3. 可选:映射方法可见性优化
虽然AutoMapper理论上可以调用私有方法,但将MapProductState改为protected或public可避免潜在的访问权限问题:
protected ProductState MapProductState(Product eqp) { // 逻辑同上 }
4. 可选:验证AutoMapper配置
添加配置验证可提前发现映射错误,避免运行时问题:
services.AddAutoMapper(config => { config.AddProfile(new ViewProductMapper()); }, AppDomain.CurrentDomain.GetAssemblies()) // 启用配置验证 .AddAutoMapperValidation();
内容的提问来源于stack exchange,提问作者Minority
相关产品推荐
相关产品推荐

