組件版本相容是常見的.NET實務問題。用以下的解決方案舉例,假設有個 MyConApp Console Application參照 MyLib Class Library,兩個專案都用NuGet裝了Newtonsot.Json(Json.NET)組件,差別在MyConApp用的是Json.NET 7.0版,MyLib用的則是6.0版。
不意外地,因為Json.NET版本不同,將會出現版本相容錯誤:
FileLoadException was unhandled
無法載入檔案或組件'Newtonsoft.Json, Version=6.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed'
理由是 MyLib 限定使用 Newtonsoft.Json.dll 6.0.0.0 版,MyConApp 雖然有 Newtonsoft.Json.dll,卻是 7.0.0.0版,不能取代 6.0.0.0 版。此時有兩種解法,第一種是將 MyLib 的 Json.NET 也升級到 7.0 重新編譯,第二種做法則是之前提過的繫結導向,修改 MyConApp App.config 加入導向設定(name 及 publicKeyToken 可以由上圖錯誤訊息取得):
這樣就可以在不更動 MyLib Json.NET 版本的狀況下順利執行。
但有一個小訣竅,如果你在 Visual Studio 重新編譯 MyLib 卻不重新編譯 MyConApp,MyConApp bin目錄下的 Newtonsoft.Json.dll 將被覆寫成 6.0.0.0 版,此時執行 MyConApp 會變成找不到 7.0.0.0 版。
這是 Visual Studio 特性使然,正常情況下,基於專案相依性 Visual Studio 會先編譯 MyLib 再編譯 MyConApp,編譯 MyLib 時 MyLib.dll 及其參照的 Newtonsot.Json.dll 將被複製到 MyConApp 的 bin 目錄,等到編譯 MyConApp 時再被覆寫成 7.0.0.0 版 Newtonsoft.Json,得到正確結果。單獨手動編譯 MyLib 時,會打破前述的覆寫順序導致錯誤。要避免上述狀況,可調整 MyLib 的 Newtonsoft.Json 設定(如下圖),取消 Copy Local,這樣編譯 MyLib 時就不會自動複製 Newtonsoft.Json 到目標資料夾,可避免非預期的覆寫結果,而引用 MyLib 的專案必須自行參照 Newtonsoft.Json,開發人員可視狀況運用。