2016-02-01 11 views
33

Mamy zespół F # (AssemblyOne), który odwołuje się do innego zestawu F # (AssemblyTwo) w pojedynczym rozwiązaniu Visual Studio 2012. AssemblyTwo ma odniesienie do biblioteki DLL C# (MyCSharpLib).Referencje zespołu F # powodujące problemy z kompilacją?

funkcji określonej w AssemblyOne wywołuje funkcję zdefiniowaną AssemblyTwo:

namespace AssemblyOne 

[<RequireQualifiedAccess>] 
module MyModuleA = 
    let FetchResult id = 
     let result = AssemblyTwo.MyModuleC.FetchResult id 
     result 

Funkcja zwana w AssemblyTwo wywołuje inną funkcję (FetchActualResult()) w tym samym zespole, który przyjmuje parametr typu MyCSharpType należącego do odpowiedniej C# DLL (MyCSharpLib):

namespace AssemblyTwo 

[<RequireQualifiedAccess>] 
module MyModuleB = 
    let FetchActualResult(myCSharpType:MyCSharpLib.MyCSharpType, id:int) 
     //return a result 

[<RequireQualifiedAccess>] 
module MyModuleC = 
    let FetchResult id = 
     let myCSharpType = new MyCSharpLib.MyCSharpType() 
     MyModuleB.FetchActualResult(myCSharpType, id) 

rozwiązanie kompiluje i buduje w Visual Studio; Jednak, gdy staramy się zbudować projekt z linii poleceń za pomocą programu MSBuild, kompilacja zakończy się niepowodzeniem, z powodu następującego błędu w msbuild.log:

error FS0074: The type referenced through 'MyCSharpLib' is defined in an assembly that is not referenced. You must add a reference to assembly 'MyCSharpLib'. 

Wydaje typ odsłoniętą jako parametr z MyCSharpLib w FetchActualResult() Podpis funkcji w AssemblyTwo powoduje błąd. AssemblyOne wymaga teraz odniesienia do MyCSharpLib, mimo że AssemblyOne nie korzysta bezpośrednio z niczego od MyCSharpLib. Jeśli usuniemy parametr z podpisu funkcji, rozwiązanie zostanie zbudowane bez błędów.

Mamy dokładniej zbadać ten problem poprzez replikację kod z następujących przypadków użycia ('->' oznacza odniesienie montaż):

  • F # AssemblyOne -> F # AssemblyTwo ->MyCSharpLib (C# DLL) (robi nie budować)
  • F # AssemblyOne -> F # AssemblyTwo ->MyFSharpLib (F # DLL) (nie tworzy)
  • F # AssemblyOne -> F # AssemblyTwo -> C# AssemblyThree (montaż w tym samym roztworze) (czy N ot build)
  • F # AssemblyOne -> F # AssemblyTwo -> F # AssemblyThree (montaż w tym samym roztworze) (buduje)

Czy takie zachowanie można wytłumaczyć?

+0

Nie jestem pewien, co to powoduje, ale zwykle można sprawdzić, czy (1) czy wszystkie odnoszą się do tej samej wersji 'FSharp.Core.dll? (2) Czy są one zestawiane dla tych samych ram docelowych? –

+0

(1) wszystkie one odnoszą się do tej samej wersji 'FSharp.Core.dll' - wersja 4.3.0.0 i (2) wszystkie struktury złożeń zestawu v4.5 – daithimurf

+1

Czy jesteś pewien, że używasz tej samej wersji MSBuild, której używa VS ? Czy możesz gdzieś umieścić pełny dziennik MSBuild? – skolima

Odpowiedz

1

Zakładając, że jest literówka w twoich źródłach, jak wskazał DWright, powiedziałbym, że ten błąd może wynikać właśnie z faktu, że tym kodem definiujesz klasę statyczną MyModuleB z odsłoniętym parametrem metody zewnętrznego typu MyCsharpType .

ten sposób kod Fsharp przekłada się IL (od ILSpy - przeliczane CSharp):

... 
public static class MyModuleB 
{ 
    public static string FetchActualResult(MyCSharpType myCSharpType, int id) 
    { 
     return myCSharpType.Fetch(id); 
    } 
} 

Jeśli nie narażać typ tak że widoczny jest statycznie, błąd nie może się pojawić. To jednak zależy od implementacji kompilatora.

Mogę sobie wyobrazić, że podczas kompilacji MyModuleA jedna konfiguracja procesu kompilacji lub wersji kompilatora może spróbować "dotknąć" MyModuleB, a tym samym spróbować dotrzeć do typu parametrów bez odniesienia, a inne mogą po prostu nie dotykać MyModuleB. To zależy.

Problem wydaje mi się nie być w procesie kompilacji, ale w tym, że narażasz na użycie typu, do którego nie odwołujesz się do jego zespołu.

0

Właśnie rozwiązałem podobny przypadek w ten sposób. Spróbuj tego.

Pod koniec MyModuleC, dodaj linię:

let fetchResult = FetchResult 

a następnie w MyModuleA, zadzwoń fetchResult zamiast FetchResult. Oczywiście z argumentem.

Tak, wiem, że to brzmi głupio, ale spróbuj. Wierzę, że złamie to niechcianą zależność.

Jeśli używasz AssemblyTwo z C# jak jest, prawdopodobnie nie będziesz mieć tego problemu. Pojawia się, gdy zużywa się AssemblyTwo z F #, więc zastanawiam się, czy jest jakiś problem z kompilatorem F #, czy może ma to coś wspólnego z curry, która jest poza mną. W każdym razie, chciałbym, żeby kompilator F # był mądrzejszy. Może ktoś powinien zgłosić problem, chyba że już to zrobiono.