Closed dsyme closed 7 years ago
The best way to get the correct set is to configure the fsi
application to include all .NET Standard 2.0 components necessary for .NET Framework 4.6.1 and up. This can be done by setting this property:
<Project>
<!-- ... -->
<PropertyGroup>
<DependsOnNETStandard>true</DependsOnNETStandard>
</PropertyGroup>
<!-- ... -->
</Project>
@cartermp @KevinRansom Given @terrajobst's advice I'd like guidance on this at some point (no huge rush). It seems that including the facade DLLs as part of the compiler seems to be the correct advice, though I think the real concern is auto-referencing them as part of the F# Interactive scripting model.
I understand the reluctance to do this. Perhaps adding just netstandard.dll is sufficient since most other facade DLLs are part of .NET 4.6.1
Anyway, I added a description of the workaround, which is to manually acquire NETStandard.Library.NETFramework and add an explicit reference to the facade DLLs you need:
#r @"packages\NETStandard.Library.NETFramework.2.0.0-preview2-25405-01\build\net461\lib\netstandard.dll"
Not pretty but it works
though I think the real concern is auto-referencing them as part of the F# Interactive scripting model.
Why would you need to auto-reference them? Presumably F# interfactive is using RefEmit to run code within the current process. The CLR should be able to load the appropriate assemblies on-demand from the fsi
directory, no?
I understand the reluctance to do this. Perhaps adding just netstandard.dll is sufficient since most other facade DLLs are part of .NET 4.6.1
True, but customers loading pre-.NET Standard 2.0 components will get pretty bad/unactionable error messages (assembly load errors, type load errors, missing member errors).
Why would you need to auto-reference them?
In the F# compilation stages being run in F# Interactive prior to RefEmit we need to follow the type forwarders to emit correct code (to understand that [netstandard]System.Int32 --> [mscorlib]System.Int32 etc.), to determine type equality etc.
True, but customers loading pre-.NET Standard 2.0 components will get pretty bad/unactionable error messages (assembly load errors, type load errors, missing member errors).
I agree this is technically possible, which is why I included the whole lot in my currently doomed PR. My estimate is that this doesn't actually happen much yet, for two reasons
For .NET Standard 1.x components there is often a .NET Framework version in the package - or portable versions. This is what people reference if it is there. Basically most F# scripters probably aren't referencing any .NET Standard 1.x components at all.
I think it will be much more common for nuget packages to only have .NET Standard 2.0 components - because a .NET Standard 2.0 is often completely adequate replacement for the .NET Framework version.
Versions (e.g. 4.0.0.0) of some assemblies like System.IO are shipped in the implementation assemblies of .NET Framework 4.6.1. F# Interactive will happily resolve to these implementation assemblies as a last resort even if System.IO 4.1.2.0 was requested in a reference and regardless of version. While this is not "sound", I suspect the forwarders in these implementation assemblies are adequate for most .NET Standard 1.x components
Strike what I said earlier; I was only thinking of runtime. In order to compile the F# code to IL you of course need to load the facades. This is proof I'm not nearly as smart as many people believe (and most don't even think that highly of me to begin with 😏 )
@terrajobst @cartermp @KevinRansom
I'll close this, since the decision was not to ship the 100 facade DLLs as part of F# Interactive, but rather apply the workaround (which feels dubious to me, but anyway...) and wait for .NET 4.7.1 to become widely spread
Workaround is:
#r @"packages/NETStandard.Library.NETFramework.2.0.0/build/net461/lib/netstandard.dll"
Perhaps there is a better way then acquiring NETStandard.Library.NETFramework
.
I believe the fact that F# Interactive doesn't play well with .NET Standard 2.0 yet is starting to bite people https://twitter.com/isaac_abraham/status/961580320897355776
@cartermp @KevinRansom Anything we can do here?
HI, I was trying to use a script file within a new sdk project while targeting net471 which depends on Newtonsoft.Json. Is the right thing to do here to depend on the net45 Newtonsoft.Json.dll or on the netstandard2.0 Newtonsoft.Json.dll?
If I reference the netstandard2.0 version, I get messages like "The type 'Enum' is required here and is unavailable. You must add a reference to assembly 'netstandard, Version=2.0.0.0...'.
I tried looking for a NETStandard.Library.NETFramework package under C:\Users{username}.nuget\packages in case it is automatically acquired by the net sdk 2.x, but did not find it. Then I installed the NETStandard.Library.NETFramework package from nuget into the project, however, this did not result in the NETStandard.Library.NETFramework package being added under the .nuget/packages folder under my home folder or anywhere else that I could track down.
Ultimately I am typically unblocked by referencing the net45 version of assemblies, but I was just wondering if I should be able to reference netstandard2.0 assemblies or not...
Starting to hit this on libraries that I can't use in FSI anymore.
Until this is fixed, could we have guidelines setup for library authors so they keep shipping binaries for full .NET framework along side netstandard ones? otherwise this is kind of splitting the ecosystem between libraries that work in FSI and those which don't.
We are seeing an issue with using Roslyn via FSI, despite using the NETStandard.Framework.Library workaround: code that compiles and runs in a .Net Core console application errors in FSI due to missing types ("type 'Microsoft.CodeAnalysis.CSharp.CSharpCompilation' not found in assembly 'Microsoft.CodeAnalysis.CSharp, Version=2.8.0.0, ...").
I have made a gist that shows how to provoke the issue: https://gist.github.com/aaron-comyn/e178636def80d898f61ce4eeead21b3b
The issue is present with the last years worth of Roslyn releases, using the same references as an operational .Net Core application. We're using FSI to introduce new datatypes into running production systems, so this issue is a bit of a 'showstopper' wrt .Net Core (System.CodeDom does not support the platform). FSI not running on .NET Standard/Core is a pain point :)
[Side note: the NETStandard.Framework.NETLibrary package is marked as deprecated... kinda confusing for FSI users who require this workaround...]
We can add EPPlus and Microsoft.Exhange.WebServices.NETStandard (unofficial .net core port of EWS), to the list. Both work fine compiled and error in FSI ( EPPlus throws a security error).
what is the status of this issue? is @dsyme 's workaround still the way to go? If so, by using the explicit reference i get problems alà DateTime is not compatible with DateTime
. Somehow i get wrong system symbols resolved randomly. I can post a repro if relevant.
The workaround is not appropriate, no. When #5850 is completed, then FSI will be able to understand packages and work with .NET Standard in a cross-platform way. Additionally, when VS 2019 is eventually shipped, it will have .NET Framework 4.7.1. (or 4.7.2, don't quite recall), which can understand .NET Standard "natively". The core issue is that FSI within VS has to target .NET Framework 4.6 today, and 4.6 has no notion of .NET Standard. Referencing 100 facade .dlls manually may work for you, but I can't say I'd recommend it.
@dsyme even with. Net 4.7.2 similar issue hapenning with canopy
@OnurGumus, until this is resolved, maybe canopy project can ship .net framework assemblies as well?
I believe you can still use older versions of the nuget for .net framework if that helps.
@OnurGumus can you provide a repro, that fails on .NET 4.7.2, I believe it should work there fine.
@KevinRansom See the attached zip file which canopy.zip only contains source but no binaries then
just call
dotnet tool install --tool-path .paket Paket
.paket\paket install
dotnet fsi test.fsx
Though let me elaborate, I am targeting .net core 3.0 SDK preview 5. It's just my machine has .net 4.7.2 sdk installed too.
It's worth noting that this is about reference .NET Standard components from the FSI that is bundled within Visual Studio, not dotnet fsi
. I think it's worth filing a separate bug for dotnet fsi
though, since that should work.
I haven't run the repro, but I can imagine what is going on.
Referencing a .NET Standard 2.0 component from F# Interactive (fsi.exe) fails with
or
Repro steps
Provide the steps required to reproduce the problem
Create a .NET Standard 2.0 component
dotnet new classlib -o -lang F# lib2 cd lib2 add code file: module Say let hello (t:System.DateTime) = printfn "the time is %A" t
dotnet restore dotnet build
Reference this from .NET Framework fsi.exe
Expected behavior
Works ok and prints the current time
Actual behavior
Known workarounds
Manually acquire the package NETStandard.Library.NETFramework
Add an explicit reference to
packages\NETStandard.Library.NETFramework.2.0.0-preview2-25405-01\build\net461\lib\netstandard.dll
e.g.Related information
master, Windows, .NET Framework 4.7 or 4.6.1