Preventing automatic framework targeting of portable class libraries - nuget

I have a library published on nuget that is targeting .NET Framework 4.5
The solution looks like:
Solution
└─ Project.Net45
The nuget package looks like:
─lib
└─net45
I wanted to add a portable class library, so I modifed the solution to:
Solution
└─ Project.Net45
└─ Project.Pcl (Targets Windows Store Apps and Windows Phone 8)
I had to modify the code in the portable class library to work around things that were not compatible with those targets such as the serializable attribute and Thread.Sleep.
The problem is that the portable class library is automatically set to target .NET Framework 4.5 with the following message:
"The following frameworks will be selected automatically because they
support all of the available functionality that is portable between
the other frameworks you have selected: .NET Framework 4.5 and
higher".
and the nuget package now looks like:
─lib
└─net45
└─portable-net45+wp80+win
If I install this nuget package into a library targeting .NET Framework 4.5, I would rather the net45 library be used rather than the portable class library as the net45 library is smaller and doesn't have all the extra code needed to work around the missing features in windows phone 8 etc).
Will changing the nuget package to structure below have the desired effect :
─lib
└─net45
└─portable-wp80+win
Or am I misunderstanding the usage of portable class libraries?

NuGet looks for the best match when adding references to assemblies in the NuGet package.
If your project targets .NET 4.5 then NuGet will install the net45 assembly since it considers that the best match.
The PCL assembly will be used when your NuGet package is added to a PCL project that is compatible.
If you only had the PCL assembly in your NuGet package then NuGet would add a reference to it if you installed it into a project that targets .NET 4.5. However since you have both it will pick the net45 assembly.

Related

Consume specific SDK dlls in Nuget package

I'm compiling my code with net6.0.
One of my depends projects, compiled with netstandard2.0, is using a Nuget package with DLLs for netstandard2.0 and net5.0 (and also netstandard1.1 and net45).
In the output folder, I see it takes the net5.0 DLL.
How can I choose to take the netstandard2.0 DLL?
The requirement is for Dotfuscator, because it looking for the net5.0 Runtime, according to that net5.0 DLL. The question should be asked about Dotfuscator, but I'm in the middle of a research to understand the Dotfuscator better, so in meanwhile I'm asking about the Nuget.
Basically, netstandard2.0 or any of the netstandard targets are actually compiled to netstandard. netstandard isn't a runtime, it's a specification of the API's that are shared between runtimes such as net5, net45, etc, allowing you to use the same codebase over different runtimes. Depending on which runtime you compile for, the netstandard library will be compiled to that.
Basically, since you are compiling your application in net6, your netstandard2.0 library is also compiling as a net6 library. It then will use the correct dependencies (the net5 one) to compile.

Choosing nuget packages would cause dependency dll hell?

Could using nuget packages cause dependency dll hell?
Example im using two nuget packages A version 1.0.0 and B in my class library
B is also heavily dependent on new feature which is non backward compatible version of A 2.0.0.
In such a case wont i get build errors? If thats the case isnt nuget scary?
Following is the very long answer. In nuget dependecies could be private when authoring
https://github.com/NuGet/Home/issues/6614
About the same issue if you are using libraries
https://devnet.kentico.com/articles/referencing-multiple-versions-of-the-same-assembly-in-a-single-application

NuGet: Force project to chose more specific target framework over netstandard

Short Version
I author a package which targets .NET Standard 1.3 and 1.6. My 1.6 build references System.Runtime.Loader. This package has a placeholder for the MonoAndroid framework, meaning my NuGet package now can not be loaded in Android 7.x projects.
My .NET Standard 1.3 build does not have this dependency. How can I force NuGet to load the netstandard-1.3 build for Android projects, instead of netstandard-1.6?
More Details
When I try and load our current package in an Android 7 project which uses project.json, I see the below error message:
System.Runtime.Loader 4.3.0 provides a compile-time reference assembly for System.Runtime.Loader on MonoAndroid,Version=v7.1, but there is no run-time assembly compatible with win.
My understanding, is that this is caused by the System.Runtime.Loader NuGet package using placeholders for a number of the target frameworks. The structure of this package, is as such:
lib -> netstandard1.5 -> System.Runtime.Loader.dll
MonoAndroid10 -> _._
I also package a netstandard-1.3 build of my package, which does not reference the System.Runtime.Loader assembly. I'm happy for Android users to get the reduced functionality in the 1.3 build - but I can't figure out how to force NuGet to pick this framework, over .NET Standard 1.6.
My current package structure is below:
lib -> netstandard1.3 -> build13.dll
netstandard1.6 -> build16.dll
I've attempted to change it to the below - to force NuGet to pick the more specific target framework, but NuGet seems to prefer netstandard1.6 over MonoAndroid. (I've also tried MonoAndroid10)
lib -> netstandard1.3 -> build13.dll
MonoAndroid -> build13.dll
netstandard1.6 -> build16.dll
Is there any way, as a package author, I can force my downstream users' Android projects to use the .NET Standard 1.3 build of my project, instead of the 1.6 build, which fails to restore due to the placeholder items in the System.Runtime.Loader package?
I eventually found this was a caching problem.
Everything I assumed about how NuGet should work was correct. The issue was that NuGet appears to cache package dependencies, so when I was rebuilding my package, it was still using the old dependency list. Annoyingly, this is only an internal cache - the Visual Studio UI made it appear that my new package's dependencies were being recognised correctly, yet the logs were showing the old dependencies being installed.
The solution was to clear the NuGet cache between each repackage.

Force NuGet to reference a .net framework 4.0 assembly in a 4.5 project?

I have two projects in my solution--one targets .net 4.0, the other targets .net 4.5. They both reference the same NuGet package which contains both 4.0 and 4.5 binaries.
How can I get NuGet to reference the same version--4.0--in both projects?
You can exclude the folder of the framework that you don't want to use (ExcludeAssets), and edit the PackageTargetFallback in your project.
In your project's csproj file:
<PackageTargetFallback Condition="'$(TargetFramework)'=='net45'">
$(PackageTargetFallback);net40
</PackageTargetFallback >
When referencing the package:
<PackageReference Include={package-ID} Version={version} ExcludeAssets="lib/$(TargetFramework)"/>
This way the package won't bring the binaries that you don't want, and the ones you want will be compatible.
Note: Taking dlls with a different target framework is not recommended.

Is there a way to create a nuget pack specifying dependencies of .NET libraries?

One of my libs has a dependency on System.Configuration but this .NET lib is not included by default in most of project types on Visual Studio. Is there a way to instruct NuGet Package Manager to add this .NET reference when installing my lib?
You can use the frameworkAssembly element in your package's nuspec file. This will cause NuGet to add a reference to the project when your package is installed.
<frameworkAssemblies>
<frameworkAssembly assemblyName="System.Configuration" />
</frameworkAssemblies>