[料理佳餚] AutoMapper 中不容忽視的 Ignore() Mapping 的順序

在有繼承關係的類別中使用 AutoMapper 為整個繼承鏈的類別做 OOM 有很多眉角需要注意,包含使用 Include 語法宣告所有派生類別的對應,以及為所有派生類別明確地建立對應地圖,就在前幾天我踩到了 Ignore() 的地雷...

假設我有一組類別是長這樣,注意一個地方,Customer.IdCustomerViewModel.Id 是不同型別。

下面這一段 Customer map 成 CustomerViewModel 的測試程式碼有兩個 Test Case,大家覺得哪一個 Test Case 會通過呢?

答案揭曉!

結果 CustomerViewModel.Id 並沒有依照我想的被 Ignore() 掉,怎麼會這樣!?

Mapping Inheritance

在 AutoMapper 的 GitHub 上有一個章節 Mapping Inheritance 在講關於有繼承關係的類別,它們的 Mapping 語法執行的順序,其中 Ignore Property Mapping 被擺在 Explicit Mapping (using .MapFrom())Inherited Explicit Mapping 之後,這是什麼意思?

我們注意一下他們提供的範例中,有一句話:

...convention has a higher priority than Ignored properties in the base class mappings...

真相大白了,基底類別對應設定中的 Ignore() 語法優先權比慣例的對應行為還要低,因此,我們在基底類別的對應設定中加幾百個 Ignore() 都沒有用。

該怎麼辦?

如果我們真的需要在這種繼承鏈的 Mapping 行為中忽略掉某個屬性,要怎麼辦?我們有兩種做法。

一、直接用 MapFrom() 語法取代 Ignore()

簡單來說,就是不要用 Ignore() 語法,我們改一下對應的設定語法。

二、在派生類別的對應設定中使用 Ignore()

我們把 Ignore() 語法移到派生類別中去設定,就變這樣,因為在派生類別中明確的對應行為會優先於慣例的對應行為。

兩種做法都可以,就看大家在不同情境下要選擇哪一種。

使用 OOM 工具必須要非常地小心,一定要清楚每個套件 Mapping 的規則及限制,否則就跟我之前使用 ForMember(destination => destination.CreatedTime, DateTime.Now); 那一次的經驗一樣,超恐怖的!

 < Source Code >

相關資源

C# 指南
ASP.NET 教學
ASP.NET MVC 指引
Azure SQL Database 教學
SQL Server 教學
Xamarin.Forms 教學