如何使用AutoMapper的ConstructUsing映射包装对象并实现解包
解决AutoMapper包装类解包为扁平对象的配置验证问题
问题原因
你当前的配置存在两个核心问题:
MyObject没有IsDeleted属性,但配置了MyObject -> MyFlatObject的映射,AutoMapper的配置验证会检查目标类型的所有成员是否有对应源成员,因此触发未映射成员错误。- 使用
ConstructUsing先通过src.Value创建MyFlatObject再手动映射IsDeleted,这种方式绕开了AutoMapper的自动成员映射逻辑,且无法通过配置验证。
正确配置方案
我们可以让AutoMapper自动处理 Value 子属性的映射,同时明确忽略 MyObject -> MyFlatObject 映射中的 IsDeleted(该属性仅来自包装类),具体配置如下:
[TestClass] public class AutoMappingTest { public interface IMyObject { } public class DeletableWrapper { public bool IsDeleted { get; set; } public IMyObject Value { get; set; } } public class MyObject : IMyObject { public bool Foo { get; set; } } public class MyFlatObject { public bool IsDeleted { get; set; } public bool Foo { get; set; } } [TestMethod] public void MappingTest() { var config = new MapperConfiguration(cfg => { // 配置MyObject到MyFlatObject,忽略IsDeleted(该属性由包装类提供) cfg.CreateMap<MyObject, MyFlatObject>() .ForMember(dest => dest.IsDeleted, opt => opt.Ignore()); // 配置包装类到扁平对象:IsDeleted来自自身,其余所有成员映射自Value子属性 cfg.CreateMap<DeletableWrapper, MyFlatObject>() .ForMember(dest => dest.IsDeleted, opt => opt.MapFrom(src => src.IsDeleted)) .ForAllOtherMembers(opt => opt.MapFrom(src => src.Value)); }); // 验证配置通过 config.AssertConfigurationIsValid(); // 可选:测试实际映射效果 var wrapper = new DeletableWrapper { IsDeleted = true, Value = new MyObject { Foo = false } }; var mapper = config.CreateMapper(); var flatObj = mapper.Map<MyFlatObject>(wrapper); Assert.AreEqual(true, flatObj.IsDeleted); Assert.AreEqual(false, flatObj.Foo); } }
配置说明
ForAllOtherMembers(opt => opt.MapFrom(src => src.Value)):告诉AutoMapper,除了已明确配置的IsDeleted之外,MyFlatObject的所有其他成员都从DeletableWrapper.Value中获取对应属性值,无需手动逐个配置。ForMember(dest => dest.IsDeleted, opt => opt.Ignore()):在MyObject -> MyFlatObject的映射中忽略IsDeleted,避免因该属性无法从MyObject获取而触发配置验证报错。- 该配置完全依赖AutoMapper的自动映射逻辑,无需手动创建
MyFlatObject实例,同时支持IMyObject派生类型的自动识别映射(只需为对应派生类型配置到MyFlatObject的映射即可)。
内容的提问来源于stack exchange,提问作者Red Riding Hood
相关产品推荐
相关产品推荐

