2012-12-17 13 views
5

Ho una soluzione con molti progetti F # e C#. Il mio obiettivo è unirli tutti a una libreria usando ILMerge. La risultante dll unita verrà inserita in un pacchetto NuGet e referenziata in altri progetti. Tuttavia, sto incontrando alcuni problemi quando la dll unita è referenziata in progetti F #.Come unire assiemi F # e C# con ILMerge in modo che tutti i tipi siano disponibili quando si fa riferimento?

Il problema che ho è che se l'assembly primario dato a ILMerge è F #, fare riferimento alla DLL risultante nel progetto F # consente di accedere solo ai tipi F #. Se C# dll viene scelto come assembly principale per l'unione, i metodi di estensione dagli assembly F # uniti non erano disponibili quando si fa riferimento nel progetto F #. Inoltre, i moduli con attributo AutoOpen non venivano più aperti in modo implicito quando si apre lo spazio dei nomi.

C'è un modo per unire assiemi F # e C# in modo che tutti i tipi (compresi i metodi di estensione) siano disponibili?

+0

Hai trovato una risposta? –

+0

Alla fine ho deciso di non usare ILMerge. Quindi sfortunatamente non ho una risposta per unire con successo gli assembly F # e C#. – Domas

risposta

4

In parte della nostra base di codice, una grande parte della libreria è fatta in F # e il resto in C#. Sia il codice F # sia il codice C# sono rivolti in avanti.

Abbiamo un file batch infernale di prendersi cura di mergeing e quello che vedo è che siamo la fusione con questo codice:

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%" 

e che fa quello che intendiamo. Tuttavia, non pubblichiamo alcun metodo di estensione né eseguiamo alcuna AutoOpen. Quello che abbiamo scoperto è stato un bug nel compilatore F # che, fino a quando non abbiamo iniziato a mettere confusione nel mix, ci ha richiesto di eseguire ildasm nell'assemblaggio di F # e strappare il codice incriminato. L'altro problema è che F # non supporta correttamente il modificatore protetto sui membri (F # li rende pubblici) quindi abbiamo creato un attributo che potremmo appendere ai membri della classe che dovevano essere protetti. Quindi abbiamo scritto uno strumento che utilizza Cecil per soffiare l'assemblaggio, strappare il nostro attributo e modificare l'accesso a tali membri a protetto (code is in the accepted answer here).

Non sapevo su AutoOpen, ma ho dovuto fare un compito simile, così ho creato classe chiamata un dichiarante che ha fatto quel tipo di lavoro come questo:

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

Poi in un costruttore statico all'interno il modulo C#, ho scritto un codice che istanzia il registrante F # usando la reflection per trovare la classe (dato che nel mio codice base il codice C# viene compilato per primo e non sa affatto che c'è il codice F #). Questo è un brutto codice con un sacco di controllo degli errori, ma funziona.