2012-12-17 48 views
5

我有許多F#和C#項目的解決方案。我的目標是使用ILMerge將它們全部合併到一個庫中。產生的合併後的dll將被放入一個NuGet包中並在其他項目中引用。但是,當F#項目中引用合併的dll時,我遇到了一些問題。如何使用ILMerge合併F#和C#程序集,以便所有類型在引用時都可用?

我遇到的問題是,如果給ILMerge的主要程序集是F#,那麼在F#項目中引用生成的dll只允許訪問F#類型。如果選擇C#dll作爲合併的主要程序集,則在F#項目中引用時,合併的F#程序集的擴展方法不可用。當打開封閉名稱空間時,帶有AutoOpen屬性的模塊也不再隱式打開。

是否有合併F#和C#程序集的方法,以便所有類型(包括擴展方法)都可用?

+0

您是否找到答案? –

+0

最後我決定不使用ILMerge。所以很遺憾,我沒有成功地合併F#和C#程序集的答案。 – Domas

回答

4

在我們的代碼庫的一部分,庫的一大塊是用F#完成的,其餘的用C#完成。 F#和C#代碼都面向前方。

我們有一個地獄般的批處理文件來照顧mergeing的和我看到的是,我們正在使用此代碼合併:

echo merging %mergeapp% /keyfile:"%keyfile%" /target:library /attr:"%dstpath%%csharpdll%" /targetplatform:%targetplatform%,%targetlib% /lib:%sllib% /lib:%targetlib% /lib:"%libpath%lib" /out:"%mergedpath%..\%csharpdll%" "%dstpath%%csharpdll%" "%dstpath%%fsharpdll%" 
%mergeapp% /keyfile:"%keyfile%" /target:library /attr:"%dstpath%%csharpdll%" /targetplatform:%targetplatform%,%targetlib% /lib:%sllib% /lib:%targetlib% /lib:"%libpath%lib" /out:"%mergedpath%..\%csharpdll%" "%dstpath%%csharpdll%" "%dstpath%%fsharpdll%" 

而且做什麼我們打算。但是,我們不會發布任何擴展方法,也不會執行任何AutoOpen。我們發現的是F#編譯器中的一個錯誤,直到我們開始混淆混淆之前,我們需要在F#程序集上運行ildasm並剔除有問題的代碼。另一個問題是F#沒有在成員上正確支持受保護的修飾符(F#使它們爲public),所以我們創建了一個屬性,可以掛在要保護的類成員上。然後,我們編寫了一個工具,使用Cecil將組件拆開,撕掉我們的屬性並將訪問權限改爲受保護的成員(code is in the accepted answer here)。

我不知道的AutoOpen,但我不得不這樣做類似的任務,所以我創建的類稱爲註冊人做那種工作是這樣的:內

type FSharpRegistrant() = 
    do 
     // do whatever I need to get going 

然後在靜態構造函數在C#模塊中,我寫了一些使用反射來實例化F#註冊者的代碼,以便找到類(因爲在我的代碼庫中C#代碼是先構建的,並且根本不知道有F#代碼)。這是很多錯誤檢查的醜陋代碼,但它的工作原理。

相關問題