If you have an existing project and want to add support for .NET Standard or .NET Core, there are three parts to consider
NOTE The .NET Sdk doesnt support just .NET Core/Standard, but also normal .NET Framework.
That mean you can create a console app/lib to just target
net461 (.NET Framework 4.6.1).
Or both, so .net core (
Easier incremental way is:
NOTE After you are comfortable with the process, you can do migration of projects in place directly.
A simple project to convert (console app with a library)
cd src dotnet new lib -lang F# -n MyLib -o MyLib.NetStandard
cd src dotnet new console -lang F# -n MyApp -o MyApp.NetCore
dotnet add MyApp.NetCore reference MyLib.NetStandard/MyLib.fsproj
slnfile in root directory
dotnet new sln -n MyApp.NetCore dotnet sln MyApp.NetCore.sln add src/MyApp.NetCore/MyApp.fsproj dotnet sln MyApp.NetCore.sln add src/MyLib.NetStandard/MyLib.fsproj
Now you can open it with VSCode, just
We want to use the original files in the new project.
delete useless source file
Library.fs generated by template
Now copy the
<Compile list to new lib from source library
fix relative path of
cd src\MyLib.NetStandard dotnet build
And now we see there is an error, because an api is missing in
error FS0039: The field, constructor or member 'AsyncDownloadString' is not defined. Maybe you want one of the following: DownloadString
By default, targeting any framework, a compiler define is added.
In this project targeting
NETSTANDARD2_0 compiler define is added.
So is possibile to
#if def the api differences. An easy way is for this is:
#if NETSTANDARD2_0 return wc.DownloadString (Uri(url)) #else return! wc.AsyncDownloadString (Uri(url)) #endif
Is not optimal, but first priority is make it work. after that, each difference can be refactored as needed.
dotnet build should pass.
You can also use custom compiler defines, if the difference is more specific (like
USE_HTTPCLIENT etc) because help reason about features used insted of just api, and make it easier
to maintain the code.
Just add that in the fsproj like
As before, just copy the
None and fix relative paths
Because .NET Core doesnt support
app.config, you can leave it there for later using a conditional check
<None Include="..\MyApp\App.config" Condition=" '$(TargetFramework)' != 'netcoreapp2.0' " />
Now, let’s try to run it
We need to use
<TargetFrameworks (plural, really, plural. I said plural already?) instead of
TargetFramework and add
There you should also add back custom compiler defines, special configuration of the original project.
All can be used with a
Condition=" '$(TargetFramework)' == 'net452' " or any other property
After that, we need to redo restore.
dotnet restore MyApp.NetCore.sln
and build it (this will build all target frameworks).
cd src\MyApp.NetCore dotnet build
and run a specific framework, like
dotnet run -f net452 dotnet run -f netcoreapp2.0
run command call
build if needed. the
build command call
restore if needed.
So most of the time, is ok just run the command you want, the
dotnet cli should do what is needed.
cd src\MyLib.NetStandard dotnet pack -c Release
dotnet pack -c Release /p:Version=1.2.3 to generate a specific version
-c Release is used to build it in
Now you can just remove the old projects, move the new fsproj and update relative paths inside fsprojs
dotnetcommands in the build script
dotnet restorethe solution, not each project :D. Same for
dotnet testcommand instead of specific tools (but depends, like