讀者Peter回饋一起MSBuild.ILMerge.Task合併錯誤案例:專案引用Manatee.Trello.WebApi套件,其依賴Microsoft.AspNet.WebApi.Client.5.2.3(System.Net.Http.Formatting.dll)及Microsoft.AspNet.WebApi.Core.5.2.3(System.Web.Http.dll),合併時出現錯誤:ILMerge.Merge: ERROR!!: Duplicate type 'System.Net.Http.HttpRequestMessageExtensions' found in assembly 'System.Web.Http'. Do you want to use the /alllowDup option?

一般來說,Namespace加上型別名稱應該是唯一的,撞名實屬罕見,引發我的好奇想一探究竟。試開一個新專案引用Manatee.Trello.WebApi與MSBuild.ILMerge.Task,合併組件時也拋出相同錯誤訊息。能重現錯誤一切好辦,著手展開調查。

手動以ILMerge.exe合併組件也出現相同錯誤,依訊息補上/allowDup參數便可避免錯誤。

依此研判,問題出在要合併的組件內含完全相同的類別名稱!使用Telerik JustDecompile分析,果真在System.Net.Http.Formatting.dll與System.Web.Http.dll發現兩個同名型別-HttpRequestMessageExtensions與MediaTypeFormatterExtensions:

 

原來這兩個型別是宣告擴充方法(Extension Method)的靜態型別,應用時完全不會用到型別名稱,故在不同DLL重複出現也無妨;一旦具有同名型別的組件要合併,名稱重複問題才會浮上檯面。

由此可知,執行ILMerge.exe時加上allowDup參數即可解決問題,但一直沒找到文件示範如何為MSBuild.ILMerge.Task加上allowDup參數。歷經一番研究,我發現合併作業的核心邏輯寫在MSBuild.ILMerge.Task.dll,反組譯發現其中有實作AllowDuplicateType參數,但似乎只能透過targets設定檔指定。

在packages\MSBuild.ILMerge.Task.1.0.2\build\MSBuild.ILMerge.Task.targets找到<MSBuild.ILMerge.Task>,加上AllowDuplicateType = "*"(或是明確列出已知的重複名稱型別,如AllowDuplicateType = "HttpRequestMessageExtensions,MediaTypeFormatterExtensions"),等同為ILMerge.exe加上/allowDup參數。(註:此種參數修改做法影響範圍將涵蓋整個解決方案)

修改後重新編譯,組件成功合併,問題排除,收工~


Comments

# by Peter

我媽問我為什麼跪在電腦前,真是太神了。 真的太感謝黑大了,大大學了一課。

# by Louis Chang

黑大有夠神。。。。

Post a comment