Sponsor: Do you build complex software systems? See how NServiceBus makes it easier to design, build, and manage software systems that use message queues to achieve loose coupling. Get started for free.
I have a tiny library that I wanted to convert to .NET Standard Library. After all was said and done, I figured it might be useful to even point out some minor things I had to deal with along the way. So here’s a mini guide on converting a library to netstandard..csproj conversion
First was I was going to convert the older csproj to the new style used for NetStandard and NetCoreApp. You have few different options here:- Create a new NetStandard Library project and copy all the files over.
- Rewrite the existing csproj file
- Use a conversion tool (CsprojToVs2017)
Package References
All your package references are now in the csproj and no longer in the packages.config. Which is glorious. This means just looking at your existing packages.config and adding the relevant <PackageReference> to your csproj.AssemblyInfo
All the assembly info is now also in the .csproj instead of being in a Properties/AssemblyInfo.cs file. This is easily translated over as well.Slim .csproj
The end result is a much smaller csproj file. Prior the file was 126 lines, and now after conversion is 18.xUnit Tests
I could not get the Visual Studio Test Runner or by callingdotnet test
to recognize the tests that are inside a netstandard library. Because of this I changed my test project to be a netcoreapp1.1
, which then worked.
NuSpec
If you are building a NuGet package, the files to be included in your nuspec file will likely have to change since the output of your assemblies will be prefixed with theTargetFramework
. In my case this now resulted in the assemblies being outputted to: bin\Release\netstandard1.6\Nancy.Gzip.dll
AppVeyor
There were a couple of changes I need to make in AppVeyor as well. First I needed to change my build worker image to Visual Studio 2017. This can be found in Settings > Environment, if you’re using the UI. As of this post, since I converted my test project to .NET Core, the tests were no longer running. This is a known issue. Current workaround is to change your Tests to be executed by a script rather than auto discovered. This way you can executedotnet test
The pain I discovered was when using a .NET Standard nuget package in a .NET Framework 4.5 project. Adding the single nuget package (actually, it was my own nuget package) brought in a ton of references to “System.Whatever” nuget packages. I am not entirely sure but I think these are shim assemblies in order to make .NET Framework support/be compatible with .NET Standard.
In any case, the fix is really simple. Build assemblies and package them in the nuget package targetting the various .NET Framework versions you wish to target *in addition to* the .NET Standard assemblies.
You change this line in your project file:
netstandard1.6
To this:
netstandard1.6;net45;net46;net47
This will build, and package, assemblies for .NET Standard as well as .NET Framework 4.5, 4.6 and 4.7.
Note the plural change to the xml element, TargetFramework became TargetFrameworks.
I went back to my own class libraries and fixed this because this was basically the one thing I didn’t like with the whole thing.
I belive the part about the dependencies will become better with .NET Standard 2.0 but for 1.x you should definitely try this yourself and see the effect (that is, create a .NET Framework console application and add your nuget package to it, observe all the dependencies brought along for the ride).
Thanks for the feedback! I did notice by just targeting netstandard1.6 that I had trouble referencing the project from a net461 project. I ended up referencing netcoreapp1.1 instead and it worked. I’ll give it a try using TargetFrameworks instead! Thanks again for the comment.
I think I understand the issue with your tests: Tests inside a netStandard DLL don’t make sense which is why that would not work. The standard is an abstraction, not a runtime. To run your tests, you need them to be executed within an implementation of the framework, not within an API specification like the standards. Change the test project to target an appropriate release of the dontnet core runtime, but referencing the netStandard library, and they should work.
Thanks for the comment! And yes, I agree with your assertion. Once I actually targeted the NetCoreApp runtime, my tests then indeed would be run by xUnit.