如何配置AutoMapper复用基类映射,避免依赖静态实例?
优化AutoMapper映射配置(依赖注入场景)
针对你遇到的依赖注入下复用基类映射、避免静态Mapper的问题,这里有两种优雅的解决方案,都能让你摆脱静态实例依赖,同时减少冗余代码:
方案1:改进AfterMap使用ResolutionContext
这是对现有代码的最小改动,只需要修改AfterMap的参数,利用AutoMapper提供的ResolutionContext获取当前的IMapper实例,完全避免静态依赖:
public class YourMappingProfile : Profile { public YourMappingProfile() { // 先配置公共基类映射 CreateMap<AnotherModel, Model>(); // EFObject → AModel 映射:复用基类映射 + 配置特有属性 CreateMap<EFObject, AModel>() .ForMember(dest => dest.AModelId, opt => opt.MapFrom(src => src.Id)) // 使用上下文里的Mapper实例,替代静态Mapper .AfterMap((src, dest, context) => context.Mapper.Map(src.AnotherModel, dest)) .ReverseMap(); // 同理配置 EFObject → BModel CreateMap<EFObject, BModel>() .ForMember(dest => dest.BModelId, opt => opt.MapFrom(src => src.Id)) .AfterMap((src, dest, context) => context.Mapper.Map(src.AnotherModel, dest)) .ReverseMap(); } }
优势:
- 几乎不需要调整现有映射结构,改造成本低
ResolutionContext.Mapper是当前注入的实例,完美适配依赖注入和单元测试场景
方案2:声明式复用基类映射(推荐)
这种方案更符合AutoMapper的设计理念,用声明式配置替代命令式的AfterMap,代码更清晰易维护:
public class YourMappingProfile : Profile { public YourMappingProfile() { // 1. 公共基类映射 CreateMap<AnotherModel, Model>(); // 2. 配置 EFObject → Model 的映射,复用上面的基类映射 CreateMap<EFObject, Model>() .ConvertUsing((src, _, context) => context.Mapper.Map<AnotherModel, Model>(src.AnotherModel)); // 3. EFObject → AModel:继承基类映射 + 配置特有属性 CreateMap<EFObject, AModel>() .IncludeBase<EFObject, Model>() .ForMember(dest => dest.AModelId, opt => opt.MapFrom(src => src.Id)) .ReverseMap(); // 4. EFObject → BModel 同理 CreateMap<EFObject, BModel>() .IncludeBase<EFObject, Model>() .ForMember(dest => dest.BModelId, opt => opt.MapFrom(src => src.Id)) .ReverseMap(); } }
优势:
- 完全遵循AutoMapper的声明式配置原则,可读性和可维护性更强
- 逻辑分层清晰:基类映射、EF到基类的转换、子类特有属性配置
单元测试示例(两种方案通用)
现在不需要初始化静态Mapper,只需要创建局部的IMapper实例即可完成测试:
[Test] public void EFObject_To_AModel_Maps_Correctly() { // 构建Mapper配置 var config = new MapperConfiguration(cfg => cfg.AddProfile<YourMappingProfile>()); var mapper = config.CreateMapper(); // 准备测试数据 var testEfObject = new EFObject { Id = 123, NestedId = 456, AnotherModel = new AnotherModel { /* 填充基类属性 */ } }; // 执行映射 var result = mapper.Map<AModel>(testEfObject); // 验证结果 Assert.AreEqual(testEfObject.Id, result.AModelId); // 验证基类属性映射是否正确 Assert.AreEqual(testEfObject.AnotherModel.BasePropertyX, result.BasePropertyX); }
这样你的单元测试就能独立运行,完全不依赖全局静态实例。
内容的提问来源于stack exchange,提问作者user3564855
相关产品推荐
相关产品推荐

