2012-12-17 17 views
5

Mam rozwiązanie z wieloma projektami F # i C#. Moim celem jest połączenie ich wszystkich w jedną bibliotekę przy użyciu ILMerge. Wynikowa połączona biblioteka dll zostanie umieszczona w pakiecie NuGet i odniesiona w innych projektach. Jednak uruchamiam się w kilku kwestiach, gdy połączona biblioteka dll jest odwoływana w projektach F #.W jaki sposób połączyć zespoły F # i C# z ILMerge tak, aby wszystkie typy były dostępne po odwołaniu?

Problem polega na tym, że jeśli podstawowym zbiorem danych ILMerge jest F #, odniesienie do wynikowego pliku dll w projekcie F # pozwala uzyskać dostęp tylko do typów F #. Jeśli plik C# dll zostanie wybrany jako zespół podstawowy do scalenia, wówczas metody rozszerzenia z scalonych zestawów F # nie były dostępne podczas odwoływania się do projektu F #. Również moduły z atrybutem AutoOpen nie były już niejawnie otwierane podczas otwierania otaczającego obszaru nazw.

Czy istnieje sposób scalania zestawów F # i C#, aby wszystkie typy (w tym metody rozszerzenia) były dostępne?

+0

Czy znalazłeś odpowiedź? –

+0

W końcu zdecydowałem się nie używać ILMerge. Tak więc niestety nie mam odpowiedzi na połączenie zespołów F # i C#. – Domas

Odpowiedz

4

W części naszej bazy kodu duża część biblioteki jest wykonywana w języku F #, a reszta w języku C#. Oba kody F # i C# są skierowane przodem do kierunku jazdy.

Mamy piekielną plik wsadowy, aby zadbać o mergeing i co widzę jest to, że łączą się z tym kodem:

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

i że robi to, co chcemy. Jednakże nie publikujemy żadnych metod rozszerzania ani nie wykonujemy żadnego AutoOpen. Odkryliśmy błąd w kompilatorze F #, który aż do momentu, w którym zaczęliśmy umieszczać zaciemnienie w miksie, wymagał od nas uruchomienia ildasm na zespole F # i wyrobienia niewłaściwego kodu. Inną kwestią jest to, że F # nie obsługuje poprawnie chronionego modyfikatora na elementach (F # czyni je publicznymi), więc stworzyliśmy atrybut, który możemy zawiesić na członkach klasy, które miały być chronione. Następnie napisaliśmy narzędzie, które wykorzystuje Cecil, aby rozerwać zespół, wyrwać nasz atrybut i zmienić dostęp do tych członków na chronione (code is in the accepted answer here).

Nie wiedziałem o AutoOpen, ale musiałem zrobić podobne zadanie, więc stworzyłem klasę o nazwie rejestrujący że zrobił tego rodzaju pracy takiego:

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

Następnie w ciągu statycznym konstruktorze moduł C#, napisałem kod, który tworzy instancję rejestrującego F # za pomocą refleksji, aby znaleźć klasę (ponieważ w mojej bazie kodu budowany jest najpierw kod C# i nie wiem, że w ogóle jest kod F #). To jest brzydki kod z dużą ilością sprawdzania błędów, ale działa.