.NET Standard 2.0 is finally publicly available as a preview release. I couldn’t help myself and took a crack at converting parts of Quino to .NET Standard just to see where we stand. To keep me honest, I did all of my investigations on my MacBook Pro in MacOS.
I installed Visual Studio for Mac, the latest JetBrains Rider EAP and .NET Standard 2.0-preview1. I already had Visual Studio Code with the C#/OmniSharp extensions installed. Everything installed easily and quickly and I was up-and-running in no time.
Armed with 3 IDEs and a powerful command line, I waded into the task.
Quino is an almost decade-old .NET Framework solution that has seen continuous development and improvement. It’s quite modern and well-modularized, but we still ran into considerable trouble when experimenting with .NET Core 1.1 almost a year ago. At the time, we dropped our attempts to work with .NET Core, but were encouraged when Microsoft shifted gears from the extremely low–surface-area API of .NET Core to the more inclusive though still considerably cleaned-up API of .NET Standard.
Since it’s an older solution, Quino projects use the older csproj file-format: the one where you have to whitelist the files to include. Instead of re-using these projects, I figured a good first step would be to use the dotnet
command-line tool to create a new solution and projects and then copy files over. That way, I could be sure that I was really only including the code I wanted—instead of random cruft generated into the project files by previous versions of Visual Studio.
dotnet
CommandThe dotnet
command is really very nice and I was able to quickly build up a list of core projects in a new solution using the following commands:
dotnet new sln
dotnet new classlib -n {name}
dotnet add reference {../otherproject/otherproject.csproj}
dotnet add package {nuget-package-name}
dotnet clean
dotnet build
That’s all I’ve used so far, but it was enough to investigate this brave new world without needing an IDE. Spoiler alert: I like it very much. The API is so straightforward that I don’t even need to include descriptions for the commands above. (Right?)
Everything really seems to be coming together: even the documentation is clean, easy-to-navigate and has very quick and accurate search results.
Encodo.Core
compiles (almost) without change. The only change required was to move project-description attributes that used to be in the AssemblyInfo.cs
file to the project file instead (where they admittedly make much more sense). If you don’t do this, the compiler complains about “[CS0579] Duplicate ‘System.Reflection.AssemblyCompanyAttribute’ attribute” and so on.Encodo.Expressions
references Windows.System.Media
for Color
and the Colors
constants. I changed those references to System.Drawing
and Color
, respectively—something I knew I would have to do.Encodo.Connections
references the .NET-Framework–only WindowsIdentity
. I will have to move these references to a Encodo.Core.Windows
project and move creation of the CurrentCredentials
, AnonymousCredentials
and UserCredentials
to a factory in the IOC.Quino.Meta
references the .NET-Framework–only WeakEventManager
. There are only two references and these are used to implement a CollectionChanged
feature that is nearly unused. I will probably have to copy/implement the WeakEventManager
for now until we can deprecate those events permanently.Quino.Data
depends on Quino.Meta.Standard
, which references System.Windows.Media
(again) as well as a few other things. The Quino.Meta.Standard
potpourri will have to be split up.I discovered all of these things using just VS Code and the command-line build. It was pretty easy and straightforward.
So far, porting to .NET Standard is a much more rewarding process than our previous attempt at porting to .NET Core.
At this point, I had a shadow copy of a bunch of the core Quino projects with new project files as well as a handful of ad-hoc changes and commented code in the source files. While OK for investigation, this was not a viable strategy for moving forward on a port for Quino.
I want to be able to work in a branch of Quino while I further investigate the viability of:
To test things out, I copied the new Encodo.Core
project file back to the main Quino workspace and opened the old solution in Visual Studio for Mac and JetBrains Rider.
Visual Studio for Mac says it’s a production release, but it stumbled right out of the gate: it failed to compile Encodo.Core
even though dotnet build
had compiled it without complaint from the get-go. Visual Studio for Mac claimed that OperatingSytem
was not available. However, according to the documentation, Operating System
is available for .NET Standard—but not in .NET Core. My theory is that Visual Studio for Mac was somehow misinterpreting my project file.
Update: After closing and re-opening the IDE, though, this problem went away and I was able to build Encodo.Core
as well. Shaky, but at least it works now.
Unfortunately, working with this IDE remained difficult. It stumbled again on the second project that I changed to .NET Standard. Encodo.Core
and Encodo.Expressions
both have the same framework property in their project files—<TargetFramework>netstandard2.0</TargetFramework>
—but, as you can see in the screenshot to the left, both are identified as .NETStandard.Library but one has version 2.0.0-preview1-25301-01 and the other has version 1.6.1. I have no idea where there second version number is coming from—it looks like this IDE is mashing up the .NET Framework version and the .NET Standard versions. Not quite ready for primetime.
Also, the application icon is mysteriously the bog-standard MacOS-app icon instead of something more…Visual Studio-y.
JetBrains Rider built the assembly without complaint, just as dotnet build
did on the command line. Rider doesn’t didn’t stumble as hard as Visual Studio for Mac, but it also didn’t had problems building projects after the framework had changed. On top of that, it wasn’t always so easy to figure out what to do to get the framework downloaded and installed. Rider still has a bit of a way to go before I would make it my main IDE.
I also noticed that, while Rider’s project/dependencies view accurately reflects .NET Standard projects, the “project properties” dialog shows the framework version as just “2.0”. The list of version numbers makes this look like I’m targeting .NET Framework 2.0.
Addtionally, Rider’s error messages in the build console are almost always truncated. The image to the right is of the IDE trying to inform me that Encodo.Logging
(which was still targeting .NET Framework 4.5) cannot reference Encodo.Core
(which references NET Standard 2.0). If you copy/paste the message into an editor, you can see that’s what it says.[1]
I don’t really know how to get Visual Studio Code to do much more than syntax-highlight my code and expose a terminal from which I can manually call dotnet build
. They write about Roslyn integration where “[o]n startup the best matching projects are loaded automatically but you can also choose your projects manually”. While I saw that the solution was loaded and recognized, I never saw any error-highlighting in VS Code. The documentation does say that it’s “optimized for cross-platform .NET Core development” and my projects targeted .NET Standard so maybe that was the problem. At any rate, I didn’t put much time into VS Code yet.
Encodo.Core
already works and there are only minor adjustments needed to be able to compile Encodo.Expressions
and Quino.Meta
.Quino.Schema
, Quino.Data.PostgreSql
, Encodo.Parsers.Antlr
and Quino.Web
. With this core, we’d be able to run the WebAPI server we’re building for a big customer on a Mac or a Linux box.I’ll keep you posted.[2]
Encodo.Expressions.AssemblyInfo.cs(14, 12): [CS0579] Duplicate ‘System.Reflection.AssemblyCompanyAttribute’ attribute
Microsoft.NET.Sdk.Common.targets(77, 5): [null] Project ‘/Users/marco/Projects/Encodo/quino/src/libraries/Encodo.Core/Encodo.Core.csproj’ targets ‘.NETStandard,Version=v2.0’. It cannot be referenced by a project that targets ‘.NETFramework,Version=v4.5’.
Encodo.Core
(NETStandard2.0) cannot be used from Encodo.Expressions
(Net462), which doesn’t seem right, but I’m not going to fight with it on this machine anymore. I’m going to try it on a fully updated Windows box next—just to remove the Mono/Mac/NETCore/Visual Studio for Mac factors from the equation. Once I’ve got things running on Windows, I’ll prepare a NETStandard project-only solution that I’ll try on the Mac.↩