Automapper映射疑问:如何让两个目标对象共享同一内部实例?
解决Automapper中共享Inner实例的映射问题
默认情况下,Automapper每次映射嵌套对象时都会创建新实例,所以即使多个源对象共享同一个InnerDto,映射后的OuterModel的InnerModel会是独立实例,无法同步修改。要实现目标实例共享,需要通过缓存已映射的Inner实例来复用。
实现步骤
- 定义实体与DTO类
public class InnerDto { public int Id { get; set; } public string Name { get; set; } } public class OuterDto { public InnerDto Inner { get; set; } } public class InnerModel { public int Id { get; set; } public string Name { get; set; } } public class OuterModel { public InnerModel Inner { get; set; } }
- 配置Automapper并添加实例缓存
使用线程安全的ConcurrentDictionary作为缓存容器,在映射InnerDto到InnerModel时复用已创建的实例:
// 缓存容器,需保证全局唯一(如单例注入) var innerInstanceCache = new ConcurrentDictionary<InnerDto, InnerModel>(); var mapperConfig = new MapperConfiguration(cfg => { // 配置InnerDto到InnerModel的映射,复用缓存实例 cfg.CreateMap<InnerDto, InnerModel>() .ConstructUsing(src => innerInstanceCache.GetOrAdd(src, dto => new InnerModel { Id = dto.Id, Name = dto.Name })); // 配置OuterDto到OuterModel的映射,默认即可 cfg.CreateMap<OuterDto, OuterModel>(); }); var mapper = mapperConfig.CreateMapper();
- 验证效果
// 创建共享的InnerDto实例 var sharedInner = new InnerDto { Id = 1, Name = "初始值" }; var outerDto1 = new OuterDto { Inner = sharedInner }; var outerDto2 = new OuterDto { Inner = sharedInner }; // 映射得到OuterModel var model1 = mapper.Map<OuterModel>(outerDto1); var model2 = mapper.Map<OuterModel>(outerDto2); // 修改其中一个的Inner属性 model1.Inner.Name = "修改后的值"; // 验证两个Inner实例是否为同一对象,且属性同步 Console.WriteLine(model1.Inner == model2.Inner); // 输出 True Console.WriteLine(model2.Inner.Name); // 输出 "修改后的值"
注意事项
- 缓存生命周期:缓存容器需保证全局唯一(如在DI中注册为单例),否则不同Mapper实例会维护各自的缓存,导致实例无法共享。
- 线程安全:使用
ConcurrentDictionary确保多线程环境下的缓存操作安全。 - 内存管理:如果源InnerDto实例会被频繁创建和销毁,需考虑添加缓存清理逻辑(如定时清理弱引用缓存),避免内存泄漏。
内容的提问来源于stack exchange,提问作者LOOK
相关产品推荐
相关产品推荐

