前幾天發現 AutoMapper 3.3 的一個性能問題(詳見:遭遇AutoMapper性能問題:映射200條數據比100條慢了近千倍),因而將 AutoMapper 升級至最新的 5.1.1 看是否也存在這個性能問題。html
升級中想固然地將以前的map配置代碼:app
Mapper.CreateMap<AEntity, ADto>();
Mapper.CreateMap<BEntity, BDto>();
改成:post
Mapper.Initialize(cfg => cfg.CreateMap<AEntity, ADto>());
Mapper.Initialize(cfg => cfg.CreateMap<BEntity, BDto>());
可是代碼運行時在執行 Mapper.Map() 時出現下面的錯誤:性能
Missing type map configuration or unsupported mapping
在執行 ProjectTo() 時出現下面的錯誤:ui
System.InvalidOperationException: Missing map from AEntity to ADto. Create using Mapper.CreateMap<AEntity, ADto>. 在 AutoMapper.QueryableExtensions.ExpressionBuilder.CreateMapExpression...
當時百思不得其解,折騰了一段時間無果,就暫時放在一邊。url
今天在博問上發現有人遇到了一樣的問題——求解AutoMapper映射類發生錯誤求解,因而解決這個問題的興趣被激發,又開始折騰。spa
在折騰的過程當中發現,若是不用 Mapper.Initialize() 這種靜態的配置方式,改用下面的實例配置方式,就不會出現這個問題。code
var config = new MapperConfiguration(cfg => cfg.CreateMap<A, B>()); var mapper = config.CreateMapper(); mapper.Map<List<B>>(list);
Mapper.Initialize() 理所固然地成了最大的嫌疑對象,因而從 GitHub 上籤出 AutoMapper 的源代碼一看 Mapper.Initialize() 的實現,恍然大悟。htm
public static void Initialize(Action<IMapperConfigurationExpression> config) { Configuration = new MapperConfiguration(config); Instance = new Mapper(Configuration); }
原來每次調用 Mapper.Initialize() 都會建立新的 Mapper 實例,也就是屢次調用 Mapper.Initialize() 只有最後一次生效。對象
下面的配置代碼中生效的只是第2行(BEntity到BDto的map),第1行(AEntity到ADto的map)沒生效,從而出現前面所說的錯誤。
Mapper.Initialize(cfg => cfg.CreateMap<AEntity, ADto>());
Mapper.Initialize(cfg => cfg.CreateMap<BEntity, BDto>());
知道了緣由,解決起來就手到擒來,改成下面的代碼便可。
var cfg = new MapperConfigurationExpression(); cfg.CreateMap<AEntity, ADto>(); cfg.CreateMap<BEntity, BDto>(); Mapper.Initialize(cfg);
解決這個問題後,成功完成了 AutoMapper 的升級,而後驗證了 AutoMapper 3.3 的性能問題在 AutoMapper 5.1.1 中不存在。