Dela via


Så här löser NuGet paketberoenden

Varje gång ett paket installeras eller installeras om, vilket inkluderar att installeras som en del av en återställning process, installerar NuGet även eventuella ytterligare paket som det första paketet är beroende av.

Dessa omedelbara beroenden kan då också ha beroenden på egen hand, vilket kan fortsätta till ett godtyckligt djup. Detta skapar vad som kallas ett beroendediagram som beskriver relationerna mellan paket på alla nivåer.

När flera paket har samma beroende kan samma paket-ID visas i diagrammet flera gånger, eventuellt med olika versionsbegränsningar. Men endast en version av ett visst paket kan användas i ett projekt, så NuGet måste välja vilken version som ska användas. Den exakta processen beror på vilket pakethanteringsformat som används.

Beroendehantering med PackageReference

När du installerar paket i projekt med formatet PackageReference lägger NuGet till referenser till ett platt paketdiagram i lämplig fil och löser konflikter i förväg. Den här processen kallas transitiv återställning. Att installera om eller återställa paket är sedan en process för att ladda ned paketen som anges i diagrammet, vilket resulterar i snabbare och mer förutsägbara versioner.

Du kan också dra nytta av flytande versioner, till exempel 2.8.*, för att undvika att ändra projektet så att det använder den senaste versionen av ett paket. Vi rekommenderar att du aktiverar låsfilsfunktionalitet när du använder rörliga versioner för att säkerställa repeterbarhet.

När NuGet-återställningsprocessen körs före en version löser den först beroenden i minnet och skriver sedan den resulterande grafen till en fil som heter project.assets.json.

Resursfilen finns på MSBuildProjectExtensionsPath, som standard är projektets obj-mapp. MSBuild läser sedan den här filen och översätter den till en uppsättning mappar där potentiella referenser kan hittas och lägger sedan till dem i projektträdet i minnet.

Filen project.assets.json är tillfällig och bör inte läggas till i källkontrollen. Den visas som standard i både .gitignore och .tfignore. Se -paket och källkontroll.

Regler för beroendehantering

Transitiv återställning tillämpar fyra huvudregler för att lösa beroenden: lägsta tillämpliga version, flytande versioner, direktberoenden har företrädeoch kusinberoenden.

Lägsta tillämpliga version

Den lägsta tillämpliga versionsregeln återställer den lägsta möjliga versionen av ett paket enligt definitionen av dess beroenden. Det gäller också för beroenden av programmet eller klassbiblioteket, om de inte deklareras som flytande.

I följande bild anses till exempel 1.0-beta vara lägre än 1,0, så NuGet väljer 1.0-versionen:

Välja den lägsta tillämpliga versionen

I nästa bild är version 2.1 inte tillgänglig i feeden, men eftersom versionsbegränsningen är >= 2.1 väljer NuGet nästa lägsta version som den kan hitta, i det här fallet 2.2:

Välja nästa lägsta tillgängliga version i feeden

När ett program anger ett exakt versionsnummer, till exempel 1.2, som inte är tillgängligt i feeden, misslyckas NuGet med ett fel när du försöker installera eller återställa paketet:

NuGet genererar ett fel när en exakt paketversion inte är tillgänglig

Flytande versioner

En flytande beroendeversion anges med *-tecknet. Till exempel 6.0.*. I den här versionsspecifikationen står det "use the latest 6.0.x version"; 4.* betyder "använd den senaste 4.x-versionen". Om du använder en flytande version minskar ändringarna i projektfilen, samtidigt som du håller dig uppdaterad med den senaste versionen av ett beroende. Flytande versioner kan bara anges på projektnivå.

När du använder en flytande version löser NuGet den högsta versionen av ett paket som matchar versionsmönstret, till exempel 6.0.* får den högsta versionen av ett paket som börjar med 6.0:

Att välja version 6.0.1 när en flytande version 6.0.* efterfrågas

Version Versioner som finns på servern Resolution Förnuft Anteckningar
* 1.1.0
1.1.1
1.2.0
1.3.0-alpha
1.2.0 Den högsta stabila versionen.
1.1.* 1.1.0
1.1.1
1.1.2-alfa
1.2.0-alfa
1.1.1 Den högsta stabila versionen som respekterar det angivna mönstret.
*-* 1.1.0
1.1.1
1.1.2-alfa
1.3.0-beta
1.3.0-beta Den högsta versionen, inklusive de inte stabila versionerna. Finns i Visual Studio version 16.6, NuGet version 5.6, .NET Core SDK version 3.1.300
1.1.*-* 1.1.0
1.1.1
1.1.2-alfa
1.1.2-beta
1.3.0-beta
1.1.2-beta Den högsta versionen som respekterar mönstret och inkluderar de inte stabila versionerna. Finns i Visual Studio version 16.6, NuGet version 5.6, .NET Core SDK version 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 Trots att detta är ett versionsintervall med en förhandsversionsdel, tillåts stabila versioner om de matchar den stabila delen. Med tanke på att 1.2.0 > 1.2.0-rc.2 är utvald.

Not

Flytande versionsmatchning tar inte hänsyn till om ett paket är listat eller inte. Lösning av flytande version löses lokalt om villkoren kan uppfyllas med paket i den globala paketmappen.

Direktberoende vinner

När paketdiagrammet för ett program innehåller olika versioner av ett paket i samma undergraf, och en av dessa versioner är ett direkt beroende i den undergrafen, väljs den versionen för den undergrafen och resten ignoreras. Det här beteendet gör att ett program kan åsidosätta alla specifika paketversioner i beroendediagrammet.

I exemplet nedan beror programmet direkt på paket B med en versionsbegränsning på >=2.0.0. Programmet är också beroende av paket A, vilket i sin tur också beror på paket B, men med en >=1.0.0-villkor. Eftersom beroendet av paket B 2.0.0 är direkt beroende av programmet i diagrammet används den versionen:

program som använder regeln direktberoende vinner

Varning

Regeln att direkt beroende vinner kan resultera i en nedgradering av paketversionen, vilket kan bryta andra beroenden i grafen. När ett paket nedgraderas lägger NuGet till en varning för att varna användaren.

Den här regeln resulterar också i större effektivitet med ett stort beroendediagram. När ett närmare beroende i samma undergraf har en högre version än en annan, ignorerar NuGet det beroendet, och NuGet ignorerar även alla återstående beroenden i den grenen av diagrammet.

I diagrammet nedan, till exempel eftersom Paket C 2.0.0 används, ignorerar NuGet alla grenar i undergrafen som refererar till en tidigare version av Paket C:

När NuGet ignorerar ett paket i diagrammet ignoreras hela grenen

Med den här regeln försöker NuGet att respektera paketförfattarens avsikt. I diagrammet nedan har författaren till Paket A uttryckligen nedgraderat till Paket C 1.0.0 från Paket C 2.0.0.

När en paketförfattare uttryckligen nedgraderar, respekterar NuGet detta.

Programägaren kan välja att uppgradera Paket C till en version som är högre än 2.0.0, vilket innebär att ingen ytterligare nedgradering av versionen för Paket C. I det här fallet utlöses ingen varning.

När en applikation lägger till ett direkt beroende av ett nedgraderat paket respekterar NuGet det.

Kusinberoenden

När olika paketversioner refereras i olika undergrafer i programgrafen, använder NuGet den lägsta versionen som uppfyller alla versionskrav (som med reglerna för den lägsta tillämpliga versionen och flytande versioner). I bilden nedan uppfyller till exempel version 2.0.0 av paket B den andra >=1.0.0-villkoret och används därför:

Att lösa kusinberoenden med den lägre versionen som uppfyller alla begränsningar

Observera att paketen inte behöver vara på samma avstånd för att regeln för kusinberoenden ska gälla. I diagrammet nedan väljs Paket D 2.0.0 i undergrafen Paket C och Paket D 3.0.0 väljs i undergrafen i paket A. I undergrafen Program finns det inget direkt beroende av paket D, så regeln lägsta tillämpliga version tillämpas och version 3.0.0 väljs.

Lösa kusinberoenden med den lägre versionen som uppfyller alla begränsningar på olika avstånd

I vissa fall går det inte att uppfylla alla versionskrav. Om paket A kräver exakt Paket B 1.0.0 och Paket C kräver Paket B >=2.0.0, kan NuGet inte lösa beroendena och ger ett fel.

olösbara beroenden på grund av ett exakt versionskrav

I dessa situationer bör toppnivå-konsumenten (programmet eller paketet) lägga till ett eget direkt beroende av paket B så att Direct-beroendet vinner och-regeln tillämpas.

Versionsintervall och förhandsversioner med PackageReference

Det är inte ovanligt att ett paket har både stabila och förhandsversioner tillgängliga. När du löser ett beroendediagram bestämmer NuGet om du vill överväga förhandsversioner för ett paket baserat på en enda 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.

I praktiken innebär följande enligt den lägsta tillämpliga regeln:

Versionsintervall Tillgängliga versioner Vald version
[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 Ingen, NU1103 höjs.
[1.0.0, 2.0.0-rc) 1.2.0-beta.1, 2.0.0-beta.3 1.2.0-beta.1

Beroendelösning med packages.config

Med packages.configskrivs ett projekts beroenden till packages.config som en platt lista. Eventuella beroenden för dessa paket skrivs också i samma lista. När paket installeras kan NuGet också ändra .csproj-filen, app.config, web.configoch andra enskilda filer.

Med packages.configförsöker NuGet lösa beroendekonflikter under installationen av varje enskilt paket. Om paket A installeras och är beroende av paket B, och paket B redan finns med i packages.config som ett beroende av något annat, jämför NuGet de versioner av paket B som begärs och försöker hitta en version som uppfyller alla versionsbegränsningar. Mer specifikt väljer NuGet den lägre major.minor- version som uppfyller beroenden.

Som standard letar NuGet 2.8 efter den lägsta korrigeringsversionen (se Viktig information om NuGet 2.8). Du kan styra den här inställningen via attributet DependencyVersion i NuGet.Config och växeln -DependencyVersion på kommandoraden.

Den packages.config processen för att lösa beroenden blir komplicerad för större beroendediagram. Varje ny paketinstallation kräver en bläddering av hela grafen och ökar risken för versionskonflikter. När en konflikt uppstår stoppas installationen, vilket lämnar projektet i ett obestämt tillstånd, särskilt med potentiella ändringar i själva projektfilen. Det här är inte ett problem när du använder andra pakethanteringsformat.

Versionsintervall och förhandsversioner med packages.config

packages.config lösning tillåter inte blandning av stabilt och förhandsversionsberoende i en graf. Om ett beroende uttrycks med ett intervall som [1.0.0, 2.0.0)tillåts inte förhandsversionspaket i diagrammet.

Hantera beroendetillgångar

När du använder PackageReference-formatet kan du styra vilka tillgångar från beroenden som flödar till projektet på den översta nivån. Mer information finns i PackageReference.

När projektet på den översta nivån i sig är ett paket har du också kontroll över det här flödet med hjälp av attributen include och exclude med beroenden som anges i .nuspec-filen. Se .nuspec-referens – Beroenden.

Exkluderande referenser

Det finns scenarier där sammansättningar med samma namn kan refereras mer än en gång i ett projekt, vilket ger upphov till design- och byggtidsfel. Överväg ett projekt som innehåller en anpassad version av C.dlloch refererar till paket C som också innehåller C.dll. Samtidigt är projektet också beroende av paket B som också är beroende av paket C och C.dll. Därför kan NuGet inte avgöra vilka C.dll att använda, men du kan inte bara ta bort projektets beroende av paket C eftersom paket B också är beroende av det.

För att lösa detta måste du direkt referera till den C.dll du vill ha (eller använda ett annat paket som refererar till det rätta) och sedan lägga till ett beroende av paket C som exkluderar alla dess tillgångar. Detta görs på följande sätt beroende på vilket pakethanteringsformat som används:

  • PackageReference: lägg till ExcludeAssets="All" i beroendet:

    <PackageReference Include="PackageC" Version="1.0.0" ExcludeAssets="All" />
    
  • packages.config: ta bort referensen till PackageC från filen .csproj så att den endast refererar till den version av C.dll som du vill använda.

Beroendeuppdateringar under paketinstallationen

Om en beroendeversion redan är uppfylld uppdateras inte beroendet under andra paketinstallationer. Överväg till exempel paket A som är beroende av paket B och anger 1.0 för versionsnumret. Källlagringsplatsen innehåller versionerna 1.0, 1.1 och 1.2 i paket B. Om A är installerat i ett projekt som redan innehåller B version 1.0 används B 1.0 fortfarande eftersom det uppfyller versionsbegränsningen. Men om paket A hade begäranden version 1.1 eller senare av B, skulle B 1.2 installeras.

Lösa inkompatibla paketfel

Under en paketåterställningsåtgärd kan du se felet "Ett eller flera paket är inte kompatibla..." eller att ett paket "inte är kompatibelt" med projektets målramverk.

Det här felet uppstår när ett eller flera av de paket som refereras i projektet inte anger att de stöder projektets målramverk. Paketet innehåller alltså inte en lämplig DLL i sin lib mapp för ett målramverk som är kompatibelt med projektet. (Se Målramverk för en lista.)

Om ett projekt till exempel riktar in sig på netstandard1.6 och du försöker installera ett paket som endast innehåller DLL:er i mapparna lib\net20 och \lib\net45 visas meddelanden som följande för paketet och eventuellt dess beroenden:

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'.

Gör något av följande för att lösa inkompatibiliteter:

  • Rikta om projektet till ett ramverk som stöds av paketen du vill använda.
  • Kontakta paketförfattaren och arbeta med dem för att lägga till stöd för ditt valda ramverk. Varje paketlistningssida på nuget.org har en Kontakta ägare-länk för detta ändamål.

Tips

Alternativ lösning: NuGetSolver är ett Visual Studio-tillägg som utvecklats av Microsoft DevLabs, utformat för att hjälpa till att lösa beroendekonflikter. Det automatiserar processen för att identifiera och åtgärda dessa problem. Mer information finns på sidan NuGetSolver på Visual Studio Marketplace och vi vill gärna höra din feedback om din upplevelse.