C# AutoMapper 7.0.1.0:如何按需排除嵌套对象自动映射?
解决AutoMapper嵌套对象映射的场景化需求
针对你在AutoMapper 7.0.1中遇到的「多数场景需要翻译Status.Title,特定场景无需翻译」的问题,这里有几个实用的解决方案,你可以根据自己的业务复杂度选择:
方案一:使用上下文参数控制翻译开关
这个方案最简洁,不需要额外定义映射规则,仅通过映射上下文传递开关参数来控制翻译逻辑:
步骤1:修改Status的映射配置
var cfg = new MapperConfigurationExpression(); // 调整Status映射,根据上下文参数决定是否执行翻译 cfg.CreateMap<Status, StatusModel>() .ForMember(dest => dest.Title, opt => opt.MapFrom((src, dest, _, context) => // 检查上下文是否携带跳过翻译的标记 context.Items.TryGetValue("SkipStatusTranslation", out var skip) && (bool)skip ? src.Title // 不翻译,直接使用原标题 : TranslateValue(src.Title) // 默认执行翻译 )) .ReverseMap(); cfg.CreateMap<Report, ReportModel>().ReverseMap();
步骤2:在特定场景下传递参数
映射时通过Items传递开关,即可跳过翻译:
// 默认场景(需要翻译) var translatedModel = mapper.Map<ReportModel>(report); // 特定场景(跳过翻译) var noTranslationModel = mapper.Map<ReportModel>(report, opt => opt.Items["SkipStatusTranslation"] = true);
这种方式的优势是无需维护多套映射,仅用参数控制逻辑,适合简单的开关式场景。
方案二:创建命名映射(Named Maps)
如果需要更明确地区分不同场景的映射规则,可以使用AutoMapper的命名映射功能,为「带翻译」和「不带翻译」分别定义独立映射:
步骤1:配置多套映射规则
var cfg = new MapperConfigurationExpression(); // 1. 默认带翻译的Status映射 cfg.CreateMap<Status, StatusModel>() .ForMember(x => x.Title, o => o.MapFrom(s => TranslateValue(s.Title))) .ReverseMap(); // 2. 不带翻译的命名Status映射 cfg.CreateMap<Status, StatusModel>("NoStatusTranslation") .ReverseMap(); // 不额外配置Title,使用AutoMapper默认映射逻辑 // 3. 默认的Report映射(复用带翻译的Status映射) cfg.CreateMap<Report, ReportModel>().ReverseMap(); // 4. 不带翻译的命名Report映射(指定使用NoStatusTranslation的Status映射) cfg.CreateMap<Report, ReportModel>("ReportNoStatusTranslation") .ForMember(dest => dest.Status, opt => opt.MapFrom(src => mapper.Map<StatusModel>(src.Status, "NoStatusTranslation"))) .ReverseMap();
步骤2:在对应场景使用命名映射
// 默认场景 var translatedModel = mapper.Map<ReportModel>(report); // 特定场景:调用命名映射 var noTranslationModel = mapper.Map<Report, ReportModel>(report, "ReportNoStatusTranslation");
这种方式适合需要为不同场景定义差异化映射规则的情况,逻辑清晰且扩展性更强。
方案三:使用独立Profile隔离映射规则
如果你的场景差异较大,甚至需要完全隔离不同的映射逻辑,可以创建独立的Profile,分别初始化不同的Mapper实例:
步骤1:定义不同的Profile
// 默认带翻译的Profile public class DefaultMappingProfile : Profile { public DefaultMappingProfile() { CreateMap<Status, StatusModel>() .ForMember(x => x.Title, o => o.MapFrom(s => TranslateValue(s.Title))) .ReverseMap(); CreateMap<Report, ReportModel>().ReverseMap(); } } // 不带翻译的Profile public class NoTranslationMappingProfile : Profile { public NoTranslationMappingProfile() { CreateMap<Status, StatusModel>().ReverseMap(); // 直接使用默认映射,不执行翻译 CreateMap<Report, ReportModel>().ReverseMap(); } }
步骤2:初始化不同的Mapper实例
// 默认Mapper(带翻译逻辑) var defaultMapper = new Mapper(new MapperConfiguration(cfg => cfg.AddProfile<DefaultMappingProfile>())); // 无翻译Mapper var noTranslationMapper = new Mapper(new MapperConfiguration(cfg => cfg.AddProfile<NoTranslationMappingProfile>()));
步骤3:在对应场景使用对应Mapper
// 默认场景 var translatedModel = defaultMapper.Map<ReportModel>(report); // 特定场景 var noTranslationModel = noTranslationMapper.Map<ReportModel>(report);
这种方案的优势是完全隔离不同的映射规则,避免相互影响,适合复杂场景下的映射管理。
以上三种方案都能满足你的需求,可根据业务复杂度灵活选择。
内容的提问来源于stack exchange,提问作者alex
相关产品推荐
相关产品推荐

