Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How NuGet resolves references when both portable and non-portable class libraries are present?

I am working on a portable class library and would like to understand the strategy used by NuGet to determine if it should use a PCL or a platform-specific library (if it exists).

I built a sample project that refers JSON.NET which has support for various platforms as well as a portable class library. Here's what JSON.NET offers from NuGet:

  • net20
  • net35
  • net40
  • sl3-wp
  • sl4
  • sl4-windowsphone71
  • winrt45
  • portable-net40+sl4+wp7+win8

First I created a library targeting NET 4.0 and added a reference to JSON.NET using NuGet. It added a reference to a net40 library. Okay, I assumed this is because there is an exact target platform match. Then I targeted NET 4.0.3. Still net40 version was referenced. Then I tried Silverlight 5 which didn't have exact match among non-portable libraries. But an sl4 library was chosen. And targeting Windows Phone 8 resulted in sl4-windowsphone71 library selection.

So it looks like whenever there is a non-portable compatible library for a target platform, it will be prioritized. In case of JSON.NET a PCL will only be selected if it's referenced by another portable library. If so, I am puzzled how the following situation will be resolved:

Library A has two versions:

  • net40
  • portable-net40+sl4+wp7+win8

Library B references A and has one version:

  • portable-net40+sl4+wp7+win8

Finally, library C references both A and B and has one version:

  • net40

How will be reference to a lib A resolved for C? Since C references A directly, it should get a net40 of A. But since C also references B which is portable, it should in addition get a portable version of A. So both portable and net40 versions of a library A must be deployed for C to resolve its dependencies. Am I correct?

UPDATE. I created a couple of test projects, and it looks like as long as a library C contains a direct reference to a non-portable library A, this version of library will win and overwrite the PCL version of A. So it looks like such scenario is not allowed - a library can't directly reference a non-portable lib if it also indirectly references a different (portable) version of it.

like image 291
Vagif Abilov Avatar asked Oct 06 '22 02:10

Vagif Abilov


1 Answers

NuGet will use the "most specific", or the "narrowest" match possible when deciding which version of a library to reference.

The portable versions of your library should be compatible with the platform-specific versions of your library. I think of this as just the more general case of compatibility between different versions of a framework. In your example, replace net40 and portable with net45 and net40. In that case, NuGet should use the .NET 4.5 version of a dependency, but if you have another dependency compiled against the .NET 4 version, it should work if at runtime it has the .NET 4.5 version instead.

To be compatible, the different versions of your library should have the same identity (name, version number, and (if applicable) strong name key), and should be API compatible, which means that a version of your library for a specific platform should have all the same APIs as a portable version that can run on that platform (the platform specific version can add additional APIs, however).

like image 103
Daniel Plaisted Avatar answered Oct 10 '22 00:10

Daniel Plaisted