I am currently in the process of migrating a library project to support .NET Standard 1.1 using Visual Studio 2017.
I was hoping to release the project as a single NuGet package that could target both .NET Framework 4.5+ and .NET Core, UWP, etc.
However, when I try to install the resulting package in .NET Framework projects, a huge list of package dependencies is generated containing all the packages defined in .NET standard (see below):
I understand that these are all the assemblies defined as part of the .NET Standard 1.1 specification. However, my specific project actually requires only a tiny subset of them, and this dependency list will be extremely confusing for anyone installing the package in their projects.
I tried to follow the answer to a similar question where the recommendation was to change the project specification to reference only the exact dependencies required by the project.
However, the answer was in the context of the old project.json format, which has now been superseded by the new .csproj format in VS 2017. I tried to remove the dependency on the .NET Standard 1.1 metapackage by removing the <TargetFramework> directive but I only managed to break the build and could not find any way to specifically add only the dependencies that were needed.
The promise of moving libraries to .NET Standard for maximum platform compatibility is extremely appealing, but what is the recommended way to structure dependencies such that projects targeting the "classic" .NET Framework do not find their projects "polluted" by all these dependencies?
Change <TargetFramework> to <TargetFrameworks> and add ;net45 to it. You still get a single NuGet package output but now it will only pull in the extra dependencies if you are targeting a .NET core app (which will have the dependencies already).
First, I'd like to point out that this is mostly a design-time issue and doesn't impact the resulting applications and the portability of your libraries:
In the past, we've given developers the recommendation to not reference the meta package (
NETStandard.Library) from NuGet packages but instead reference individual packages, likeSystem.RuntimeandSystem.Collections. The rationale was that we thought of the meta package as a shorthand for a bunch of packages that were the actual atomic building blocks of the .NET platform. The assumption was: we might end up creating another .NET platform that only supports some of these atomic blocks but not all of > them. There were also concerns regarding how our tooling deals with large package graphs.Moving forward, we'll simplify this:
.NET Standard is an atomic building block. In other words, new platforms aren't allowed to subset .NET Standard -- they have to implement all of it.
We're moving away from using packages to describe our platforms, including .NET Standard.
This means, you'll not have to reference any NuGet packages for .NET Standard anymore. You expressed your dependency with the lib folder, which is exactly how it has worked for all other .NET platforms, in particular .NET Framework.
However, right now our tooling will still burn in the reference to
NETStandard.Library. There is no harm in that either, it will just become redundant moving forward.
However, I fully acknowledge that this outcome is hardly desirable.
With .NET Standard 1.x and packages.config, you have unfortunately no choice but to produce a handwritten .nuspec with custom dependency groups. However, this requires understanding which packages are required and tends to be fragile. If the consumer uses <PackageReference> it's slightly less of a headache because it separates direct- from transitive references, and thus these are not that much in your face.
With .NET Standard 2.0 the problem will go away entirely.
If you look at those package references for net45 you will find there are no actual DLL's to load. The package is there so that runtimes such as the coreclr which loads all parts of the BCL as dll's can get them. However in net45, you won't actually find any dll's in those packages.
In short, in .net 4.x, .net will still use the GAC, to load those assemblies.