Hoe NuGet pakketafhankelijkheden oplost
Telkens wanneer een pakket wordt geïnstalleerd of opnieuw wordt geïnstalleerd, waaronder wordt geïnstalleerd als onderdeel van een herstelproces, installeert NuGet ook eventuele extra pakketten waarvan het eerste pakket afhankelijk is.
Deze directe afhankelijkheden kunnen dan ook afhankelijkheden hebben, die zich op een willekeurige diepte kunnen voortzetten. Dit produceert een afhankelijkheidsgrafiek die de relaties tussen pakketten op alle niveaus beschrijft.
Wanneer meerdere pakketten dezelfde afhankelijkheid hebben, kan dezelfde pakket-id meerdere keren in de grafiek worden weergegeven, mogelijk met verschillende versiebeperkingen. Er kan echter slechts één versie van een bepaald pakket worden gebruikt in een project, dus NuGet moet kiezen welke versie wordt gebruikt. Het exacte proces is afhankelijk van de gebruikte indeling voor pakketbeheer.
Afhankelijkheidsoplossing met PackageReference
Wanneer u pakketten in projecten installeert met behulp van de PackageReference-indeling, voegt NuGet verwijzingen toe aan een vlakke pakketgrafiek in het juiste bestand en worden conflicten vooraf opgelost. Dit proces wordt aangeduid als transitieve herstelbewerking. Het opnieuw installeren of herstellen van pakketten is dan een proces van het downloaden van de pakketten die in de grafiek worden vermeld, wat resulteert in snellere en voorspelbarere builds.
U kunt ook profiteren van zwevende versies, zoals 2.8.*, om te voorkomen dat u het project wijzigt om de nieuwste versie van een pakket te gebruiken. Wanneer u zwevende versies gebruikt, raden we u aan de functionaliteit van het vergrendelingsbestand in te schakelen om herhaalbaarheid te garanderen.
Wanneer het NuGet-herstelproces wordt uitgevoerd vóór een build, worden eerst afhankelijkheden in het geheugen omgezet. Vervolgens wordt de resulterende grafiek naar een bestand met de naam project.assets.json
geschreven.
Het assetsbestand bevindt zich in MSBuildProjectExtensionsPath
, die standaard wordt gebruikt in de map obj van het project.
MSBuild leest dit bestand vervolgens en vertaalt het in een set mappen waar potentiële verwijzingen kunnen worden gevonden en voegt deze vervolgens toe aan de projectstructuur in het geheugen.
Het project.assets.json
-bestand is tijdelijk en mag niet worden toegevoegd aan broncodebeheer. Deze wordt standaard vermeld in zowel .gitignore
als .tfignore
. Zie pakketten en broncodebeheer.
Regels voor afhankelijkheidsoplossing
Transitive restore past vier hoofdregels toe om afhankelijkheden op te lossen: laagste toepasselijke versie, zwevende versies, direct-dependency-winsen neefafhankelijkheden.
Laagste toepasselijke versie
Met de laagst toepasselijke versieregel wordt de laagst mogelijke versie van een pakket hersteld, zoals gedefinieerd door de afhankelijkheden. Het is ook van toepassing op afhankelijkheden van de toepassing of de klassebibliotheek, tenzij deze is gedeclareerd als zwevende.
In de volgende afbeelding wordt bijvoorbeeld 1.0-beta beschouwd als lager dan 1.0, zodat NuGet de versie 1.0 kiest:
In de volgende afbeelding is versie 2.1 niet beschikbaar in de feed, maar omdat de versiebeperking is >= 2.1 NuGet kiest de volgende laagste versie die deze kan vinden, in dit geval 2.2:
Wanneer een toepassing een exact versienummer opgeeft, zoals 1.2, dat niet beschikbaar is in de feed, mislukt NuGet met een fout bij het installeren of herstellen van het pakket:
Zwevende versies
Er wordt een zwevende afhankelijkheidsversie opgegeven met het teken *. Bijvoorbeeld 6.0.*
. Deze versiespecificatie geeft aan dat u de nieuwste versie 6.0.x gebruikt; 4.*
betekent 'de nieuwste 4.x-versie gebruiken'. Als u een zwevende versie gebruikt, worden wijzigingen in het projectbestand verminderd, terwijl u up-to-date blijft met de nieuwste versie van een afhankelijkheid.
Zwevende versies kunnen alleen worden opgegeven op projectniveau.
Wanneer u een zwevende versie gebruikt, wordt in NuGet de hoogste versie van een pakket omgezet dat overeenkomt met het versiepatroon, bijvoorbeeld 6.0.*
de hoogste versie van een pakket krijgt dat begint met 6.0:
Versie | Versies die aanwezig zijn op de server | Resolutie | Reden | Notities |
---|---|---|---|---|
* | 1.1.0 1.1.1 1.2.0 1.3.0-alpha |
1.2.0 | De hoogste stabiele versie. | |
1.1.* | 1.1.0 1.1.1 1.1.2-alfa 1.2.0-alfa |
1.1.1 | De hoogste stabiele versie die het opgegeven patroon respecteert. | |
*-* | 1.1.0 1.1.1 1.1.2-alfa 1.3.0-bèta |
1.3.0-bèta | De hoogste versie, inclusief de niet stabiele versies. | Beschikbaar in Visual Studio versie 16.6, NuGet versie 5.6, .NET Core SDK versie 3.1.300 |
1.1.*-* | 1.1.0 1.1.1 1.1.2-alfa 1.1.2-bèta 1.3.0-bèta |
1.1.2-bèta | De hoogste versie die het patroon respecteert en inclusief de niet-stabiele versies. | Beschikbaar in Visual Studio versie 16.6, NuGet versie 5.6, .NET Core SDK versie 3.1.300 |
1.2.0-rc.* | 1.1.0 1.2.0-rc.1 1.2.0-rc.2 1.2.0 |
1.2.0 | Ondanks dat dit een versiebereik met een prerelease-deel is, zijn stabiele versies toegestaan als ze overeenkomen met het stabiele deel. Aangezien 1.2.0 > 1.2.0-rc.2 is, is deze gekozen. |
Notitie
Flexibele versie-resolutie houdt geen rekening met het al dan niet vermelden van een pakket. Het oplossen van zwevende versieproblemen gebeurt lokaal als aan de voorwaarden kan worden voldaan met pakketten in de globale pakketmap.
Directe afhankelijkheid wint
Wanneer de pakketgrafiek voor een toepassing verschillende versies van een pakket in dezelfde subgraaf bevat en een van deze versies een directe afhankelijkheid in die subgraaf is, wordt die versie voor die subgraaf gekozen en wordt de rest genegeerd. Met dit gedrag kan een toepassing een bepaalde pakketversie in de afhankelijkheidsgrafiek overschrijven.
In het onderstaande voorbeeld is de toepassing rechtstreeks afhankelijk van Pakket B met een versiebeperking van >=2.0.0. De toepassing is ook afhankelijk van Pakket A die op zijn beurt ook afhankelijk is van Pakket B, maar met een beperking >=1.0.0. Omdat de afhankelijkheid van pakket B 2.0.0 directe afhankelijkheid is van de toepassing in de grafiek, wordt die versie gebruikt:
Waarschuwing
De regel voor directe afhankelijkheid wint kan leiden tot een downgrade van de pakketversie, waardoor andere afhankelijkheden in de grafiek mogelijk worden onderbroken. Wanneer een pakket wordt verlaagd in versie, voegt NuGet een waarschuwing toe om de gebruiker te informeren.
Deze regel resulteert ook in een grotere efficiëntie met een grote afhankelijkheidsgrafiek. Wanneer een grotere afhankelijkheid in dezelfde subgraaf een hogere versie heeft dan een andere, negeert NuGet die afhankelijkheid en negeert NuGet ook alle resterende afhankelijkheden van die vertakking van de grafiek.
In het onderstaande diagram, bijvoorbeeld omdat Pakket C 2.0.0 wordt gebruikt, negeert NuGet alle vertakkingen in die subgraaf die verwijzen naar een eerdere versie van Pakket C:
Via deze regel probeert NuGet de intentie van de auteur van het pakket te respecteren. In het onderstaande diagram heeft de auteur van Package A expliciet een downgrade uitgevoerd naar Package C 1.0.0 van Package C 2.0.0.
De eigenaar van de toepassing kan ervoor kiezen om Pakket C te upgraden naar een versie die hoger is dan 2.0.0, waardoor de versie voor Pakket C niet verder wordt gedegraded. In dit geval wordt er geen waarschuwing gegenereerd.
Nevenafhankelijkheden
Wanneer verschillende pakketversies in verschillende subgrafieken in de grafiek van de toepassing worden genoemd, gebruikt NuGet de laagste versie die voldoet aan alle versievereisten (zoals met de laagste toepasselijke versie en zwevende versies regels). In de onderstaande afbeelding, bijvoorbeeld versie 2.0.0 van pakket B, voldoet aan de andere beperking >=1.0.0 en wordt dus gebruikt:
Houd er rekening mee dat de pakketten niet op dezelfde afstand hoeven te staan om de regel voor neefafhankelijkheden toe te passen. In het onderstaande diagram wordt Package D 2.0.0 gekozen in de subgraaf Van Pakket C en pakket D 3.0.0 gekozen in de subgraaf van Pakket A. In de subgraaf van de toepassing is er geen directe afhankelijkheid van Pakket D, dus de laagste toepasselijke versie regel wordt toegepast en versie 3.0.0 wordt gekozen.
In sommige gevallen is het niet mogelijk om te voldoen aan alle versievereisten. Zoals hieronder wordt weergegeven, kan NuGet, als Pakket A exact Pakket B 1.0.0 vereist en Pakket C pakket B >=2.0.0 vereist, de afhankelijkheden niet oplossen en een fout geven.
In deze situaties moet de consument op het hoogste niveau (de toepassing of het pakket) een eigen directe afhankelijkheid toevoegen aan pakket B, zodat de Directe afhankelijkheid wint regel van toepassing is.
Versiebereiken en voorlopige versies met PackageReference
Het is niet ongebruikelijk dat een pakket zowel stabiele als voorlopige versies beschikbaar heeft.
Bij het oplossen van een afhankelijkheidsgrafiek bepaalt NuGet of u voorlopige versies voor een pakket wilt overwegen op basis van één regel: If the project or any packages within the graph request a prerelease version of a package, then include both prerelease or stable versions, otherwise consider stable versions only.
In de praktijk betekent dit onder de laagste toepasselijke regel:
Versiebereik | Beschikbare versies | Geselecteerde versie |
---|---|---|
[1.0.0, 2.0.0) | 1.2.0-beta.1, 1.2.0, | 1.2.0 |
[1.0.0, 2.0.0-0) | 1.2.0-beta.1, 1.2.0, | 1.2.0-beta.1 |
[1.0.0, 2.0.0) | 1.2.0-beta.1, 2.0.0-beta.3 | Geen, NU1103 wordt verhoogd. |
[1.0.0, 2.0.0-rc) | 1.2.0-beta.1, 2.0.0-beta.3 | 1.2.0-beta.1 |
Afhankelijkheidsoplossing met packages.config
Met packages.config
worden de afhankelijkheden van een project naar packages.config
geschreven als een platte lijst. Alle afhankelijkheden van deze pakketten worden ook in dezelfde lijst geschreven. Wanneer pakketten zijn geïnstalleerd, kan NuGet ook het .csproj
-bestand, app.config
, web.config
en andere afzonderlijke bestanden wijzigen.
Met packages.config
probeert NuGet afhankelijkheidsconflicten op te lossen tijdens de installatie van elk afzonderlijk pakket. Als Pakket A wordt geïnstalleerd en afhankelijk is van Pakket B en Pakket B al wordt vermeld in packages.config
als afhankelijkheid van iets anders, vergelijkt NuGet de versies van Pakket B die worden aangevraagd en probeert een versie te vinden die voldoet aan alle versiebeperkingen. Met name nuGet selecteert de lagere major.minor-versie die voldoet aan afhankelijkheden.
Standaard zoekt NuGet 2.8 naar de laagste patchversie (zie Releaseopmerkingen bij NuGet 2.8). U kunt deze instelling beheren via het kenmerk DependencyVersion
in NuGet.Config
en de -DependencyVersion
schakeloptie via de opdrachtregel.
Het packages.config
proces voor het oplossen van afhankelijkheden wordt ingewikkeld voor grotere afhankelijkheidsgrafieken. Elke nieuwe pakketinstallatie vereist een doorkruising van de hele grafiek en verhoogt de kans op versieconflicten. Wanneer er een conflict optreedt, wordt de installatie gestopt, waardoor het project een onbepaalde status heeft, met name met mogelijke wijzigingen in het projectbestand zelf. Dit is geen probleem bij het gebruik van andere indelingen voor pakketbeheer.
Versiebereiken en voorlopige versies met packages.config
packages.config resolutie staat het combineren van stabiele en voorlopige afhankelijkheid in een grafiek niet toe.
Als een afhankelijkheid wordt uitgedrukt met een bereik zoals [1.0.0, 2.0.0)
, zijn voorlopige pakketten niet toegestaan in de grafiek.
Afhankelijkheidsassets beheren
Wanneer u de PackageReference-indeling gebruikt, kunt u bepalen welke assets van afhankelijkheden naar het project op het hoogste niveau stromen. Zie PackageReferencevoor meer informatie.
Wanneer het project op het hoogste niveau zelf een pakket is, hebt u ook controle over deze stroom met behulp van de include
- en exclude
kenmerken met afhankelijkheden die worden vermeld in het .nuspec
-bestand. Zie .nuspec Reference - Afhankelijkheden.
Uitsluiten van verwijzingen
Er zijn scenario's waarin meerdere assembly's met dezelfde naam kunnen worden verwezen in een project, waardoor ontwerp- en buildtijdfouten worden gegenereerd. Overweeg een project met een aangepaste versie van C.dll
en verwijst naar Pakket C die ook C.dll
bevat. Tegelijkertijd is het project ook afhankelijk van Pakket B, die ook afhankelijk is van Pakket C en C.dll
. Als gevolg hiervan kan NuGet niet bepalen welke C.dll
te gebruiken, maar u kunt niet alleen de afhankelijkheid van het project op Pakket C verwijderen, omdat Pakket B er ook van afhankelijk is.
Om dit op te lossen, moet u rechtstreeks verwijzen naar de gewenste C.dll
(of een ander pakket gebruiken dat verwijst naar de juiste) en vervolgens een afhankelijkheid toevoegen van Pakket C die alle assets uitsluit. Dit gebeurt als volgt, afhankelijk van de pakketbeheerindeling die wordt gebruikt:
PackageReference-: voeg
ExcludeAssets="All"
toe aan de afhankelijkheid:<PackageReference Include="PackageC" Version="1.0.0" ExcludeAssets="All" />
packages.config
: verwijder de verwijzing naar PackageC uit het.csproj
-bestand, zodat deze alleen verwijst naar de gewenste versie vanC.dll
.
Afhankelijkheidsupdates tijdens de installatie van het pakket
Als er al aan een afhankelijkheidsversie wordt voldaan, wordt de afhankelijkheid niet bijgewerkt tijdens andere pakketinstallaties. Denk bijvoorbeeld aan pakket A die afhankelijk is van pakket B en geeft 1.0 op voor het versienummer. De bronopslagplaats bevat versies 1.0, 1.1 en 1.2 van pakket B. Als A is geïnstalleerd in een project dat al B versie 1.0 bevat, blijft B 1.0 in gebruik omdat deze voldoet aan de versiebeperking. Als pakket A echter aanvragen van versie 1.1 of hoger van B had, zou B 1.2 worden geïnstalleerd.
Incompatibele pakketfouten oplossen
Tijdens een herstelbewerking van een pakket ziet u mogelijk de fout 'Een of meer pakketten zijn niet compatibel...' of dat een pakket 'niet compatibel' is met het doelframework van het project.
Deze fout treedt op wanneer een of meer van de pakketten waarnaar in uw project wordt verwezen, niet aangeven dat ze het doelframework van het project ondersteunen; Dat wil gezegd, het pakket bevat geen geschikte DLL in de lib
map voor een doelframework dat compatibel is met het project. (Zie Target Frameworks voor een lijst.)
Als een project bijvoorbeeld is gericht op netstandard1.6
en u probeert een pakket te installeren dat alleen DLL's bevat in de mappen lib\net20
en \lib\net45
, ziet u berichten zoals het volgende voor het pakket en mogelijk de afhankelijke items:
Restoring packages for myproject.csproj...
Package ContosoUtilities 2.1.2.3 is not compatible with netstandard1.6 (.NETStandard,Version=v1.6). Package ContosoUtilities 2.1.2.3 supports:
- net20 (.NETFramework,Version=v2.0)
- net45 (.NETFramework,Version=v4.5)
Package ContosoCore 0.86.0 is not compatible with netstandard1.6 (.NETStandard,Version=v1.6). Package ContosoCore 0.86.0 supports:
- 11 (11,Version=v0.0)
- net20 (.NETFramework,Version=v2.0)
- sl3 (Silverlight,Version=v3.0)
- sl4 (Silverlight,Version=v4.0)
One or more packages are incompatible with .NETStandard,Version=v1.6.
Package restore failed. Rolling back package changes for 'MyProject'.
Ga op een van de volgende manieren te werk om compatibiliteitsproblemen op te lossen:
- Uw project opnieuw instellen op een framework dat wordt ondersteund door de pakketten die u wilt gebruiken.
- Neem contact op met de auteur van de pakketten en werk ermee samen om ondersteuning voor uw gekozen framework toe te voegen. Elke pagina met pakketvermeldingen op nuget.org heeft hiervoor een Contacteer eigenaren koppeling.
Tip
Alternatieve oplossing: NuGetSolver is een Visual Studio-extensie die is ontwikkeld door Microsoft DevLabs, ontworpen om te helpen bij het oplossen van afhankelijkheidsconflicten. Het automatiseert het proces voor het identificeren en oplossen van deze problemen. Ga voor meer informatie naar de pagina NuGetSolver op Visual Studio Marketplace en we horen graag uw feedback over uw ervaring.