Freigeben über


So löst NuGet Paketabhängigkeiten auf

Jedes Mal, wenn ein Paket installiert oder neu installiert wird, einschließlich der Installation als Teil eines Wiederherstellens Prozess, installiert NuGet auch alle zusätzlichen Pakete, von denen dieses erste Paket abhängt.

Diese unmittelbaren Abhängigkeiten können dann auch eigene Abhängigkeiten haben, die weiterhin eine beliebige Tiefe aufweisen können. Dadurch wird ein Abhängigkeitsdiagramm erzeugt, das die Beziehungen zwischen Paketen auf allen Ebenen beschreibt.

Wenn mehrere Pakete dieselbe Abhängigkeit aufweisen, kann die gleiche Paket-ID mehrmals im Diagramm angezeigt werden, möglicherweise mit unterschiedlichen Versionsbeschränkungen. Es kann jedoch nur eine Version eines bestimmten Pakets in einem Projekt verwendet werden, sodass NuGet auswählen muss, welche Version verwendet wird. Der genaue Prozess hängt vom verwendeten Paketverwaltungsformat ab.

Abhängigkeitsauflösung mit PackageReference

Beim Installieren von Paketen in Projekten mit dem PackageReference-Format fügt NuGet Verweise auf ein flaches Paketdiagramm in der entsprechenden Datei hinzu und löst Konflikte im Voraus. Dieser Prozess wird als transitive Wiederherstellungbezeichnet. Das erneute Installieren oder Wiederherstellen von Paketen ist dann ein Prozess des Herunterladens der im Diagramm aufgeführten Pakete, was zu schnelleren und vorhersehbareren Builds führt.

Sie können auch unverankerte Versionen wie 2.8.*nutzen, um zu vermeiden, dass das Projekt geändert wird, um die neueste Version eines Pakets zu verwenden. Bei Verwendung variabler Versionen wird empfohlen, die -Sperrdateifunktionalität zu aktivieren, um die Wiederholbarkeit sicherzustellen.

Wenn der NuGet-Wiederherstellungsvorgang vor einem Build ausgeführt wird, werden abhängigkeiten zuerst im Arbeitsspeicher aufgelöst, und anschließend wird das resultierende Diagramm in eine Datei mit dem Namen project.assets.jsongeschrieben.

Die Assets-Datei befindet sich in MSBuildProjectExtensionsPath, welche standardmäßig im 'obj'-Ordner des Projekts liegt. MSBuild liest diese Datei und übersetzt sie in eine Reihe von Ordnern, in denen potenzielle Verweise gefunden werden können, und fügt sie dann der Projektstruktur im Arbeitsspeicher hinzu.

Die project.assets.json Datei ist temporär und sollte nicht zur Quellcodeverwaltung hinzugefügt werden. Sie ist standardmäßig in .gitignore und .tfignoreaufgeführt. Siehe Pakete und Quellenkontrolle.

Regeln zur Abhängigkeitsauflösung

Transitive Wiederherstellung wendet vier Hauptregeln zum Auflösen von Abhängigkeiten an: niedrigste anwendbare Version, schwebende Versionen, direkte Abhängigkeiten gewinnenund verwandte Abhängigkeiten.

Niedrigste anwendbare Version

Die niedrigste anwendbare Versionsregel stellt die niedrigste mögliche Version eines Pakets wieder her, wie durch seine Abhängigkeiten definiert. Sie gilt auch für Abhängigkeiten von der Anwendung oder der Klassenbibliothek, es sei denn, sie wird als flexibledeklariert.

In der folgenden Abbildung wird z. B. 1.0-Beta als niedriger als 1.0 betrachtet, sodass NuGet die Version 1.0 auswäht:

Auswählen der niedrigsten anwendbaren Version

In der nächsten Abbildung ist Version 2.1 nicht für den Feed verfügbar, aber da die Versionseinschränkung >= 2.1 NuGet die nächste niedrigste Version auswählt, die sie finden kann, in diesem Fall 2.2:

Auswählen der nächstniedrigsten Version im Feed

Wenn eine Anwendung eine genaue Versionsnummer angibt, z. B. 1.2, die für den Feed nicht verfügbar ist, schlägt NuGet beim Versuch, das Paket zu installieren oder wiederherzustellen, fehl:

NuGet generiert einen Fehler, wenn eine genaue Paketversion nicht verfügbar ist

Schwebende Versionen

Eine fließende Abhängigkeitsversion wird mit dem Zeichen * angegeben. Beispiel: 6.0.*. Diese Versionsspezifikation besagt "die neueste Version von 6.0.x verwenden"; 4.* bedeutet "die neueste Version von 4.x verwenden". Durch die Verwendung einer unverankerten Version werden Änderungen an der Projektdatei reduziert, während sie mit der neuesten Version einer Abhängigkeit auf dem neuesten Stand bleiben. Fließende Versionen können nur auf Projektebene festgelegt werden.

Bei Verwendung einer unverankerten Version löst NuGet die höchste Version eines Pakets auf, das dem Versionsmuster entspricht, z. B. 6.0.* ruft die höchste Version eines Pakets ab, das mit 6.0 beginnt:

Auswählen von Version 6.0.1, wenn eine unverankerte Version 6.0.* angefordert wird,

Version Versionen, die auf dem Server vorhanden sind Auflösung Grund Notizen
* 1.1.0
1.1.1
1.2.0
1.3.0-Alpha
1.2.0 Die höchste stabile Version.
1.1.* 1.1.0
1.1.1
1.1.2-Alpha
1.2.0-Alpha
1.1.1 Die höchste stabile Version, die das angegebene Muster respektiert.
*-* 1.1.0
1.1.1
1.1.2-Alpha
1.3.0-Beta
1.3.0-Beta Die höchste Version einschließlich der nicht stabilen Versionen. Verfügbar in 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-Alpha
1.1.2-Beta
1.3.0-Beta
1.1.2-Beta Die höchste Version, die das Muster respektiert und die nicht stabilen Versionen enthält. Verfügbar in 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 Obwohl es sich um einen Versionsbereich mit einer Vorabversion handelt, sind stabile Versionen zulässig, wenn sie mit dem stabilen Teil übereinstimmen. Da 1.2.0 > 1.2.0-rc.2 gewählt wird, ist sie die gewählte Version.

Anmerkung

Die dynamische Versionsauflösung berücksichtigt nicht, ob ein Paket vorhanden ist oder nicht. Die schwebende Versionsauflösung wird lokal durchgeführt, wenn die Bedingungen mit Paketen im Globalen Paketordner erfüllt werden können.

Direkte Abhängigkeit gewinnt

Wenn das Paketdiagramm für eine Anwendung unterschiedliche Versionen eines Pakets in demselben Untergraph enthält und eine dieser Versionen eine direkte Abhängigkeit in diesem Untergraph ist, wird diese Version für dieses Untergraph ausgewählt, und der Rest wird ignoriert. Dieses Verhalten ermöglicht es einer Anwendung, eine bestimmte Paketversion im Abhängigkeitsdiagramm außer Kraft zu setzen.

Im folgenden Beispiel hängt die Anwendung direkt von Paket B mit einer Versionsbeschränkung von >=2.0.0 ab. Die Anwendung hängt auch von Paket A ab, die wiederum von Paket B abhängt, aber mit einer >=1.0.0-Einschränkung. Da die Abhängigkeit von Package B 2.0.0 direkte Abhängigkeit von der Anwendung im Diagramm ist, wird diese Version verwendet:

Anwendung, die nach der Regel der direkten Abhängigkeit gewinnt

Warnung

Die Regel, dass Direktabhängigkeit gewinnt, kann zu einem Downgrade der Paketversion führen und dadurch möglicherweise andere Abhängigkeiten im Graphen beeinträchtigen. Wenn ein Paket herabgestuft wird, fügt NuGet eine Warnung hinzu, um den Benutzerzu benachrichtigen.

Diese Regel führt auch zu einer höheren Effizienz mit einem großen Abhängigkeitsdiagramm. Wenn eine engere Abhängigkeit im selben Untergraphen eine höhere Version als ein weiteres aufweist, ignoriert NuGet diese Abhängigkeit, und NuGet ignoriert auch alle verbleibenden Abhängigkeiten von diesem Zweig des Diagramms.

Im folgenden Diagramm, z. B. weil Package C 2.0.0 verwendet wird, ignoriert NuGet alle Verzweigungen in diesem Untergraphen, die auf eine frühere Version von Package C verweisen:

Wenn NuGet ein Paket im Diagramm ignoriert, ignoriert es diesen gesamten Verzweigungszweig

Durch diese Regel versucht NuGet, die Absicht des Paketautors zu berücksichtigen. Im folgenden Diagramm hat der Autor von Package A das Paket C von Version 2.0.0 auf Version 1.0.0 explizit herabgestuft.

Wenn ein Paketautor explizit ein Downgrade vornimmt, berücksichtigt NuGet dies.

Der Anwendungsbesitzer kann das Upgrade von Package C auf eine Version höher als 2.0.0 auswählen und somit keine weitere Herabstufung der Version für Package C durchführen. In diesem Fall wird keine Warnung ausgelöst.

Wenn eine Anwendung eine direkte Abhängigkeit für ein herabgestuftes Paket hinzufügt, berücksichtigt NuGet dies.

Abhängigkeiten zwischen Cousins

Wenn unterschiedliche Paketversionen in verschiedenen Untergraphen im Diagramm aus der Anwendung referenziert werden, verwendet NuGet die niedrigste Version, die alle Versionsanforderungen erfüllt (wie bei der niedrigsten anwendbaren Version und unverankerten Versionen Regeln). In der folgenden Abbildung erfüllt Version 2.0.0 von Package B die andere >=1.0.0-Einschränkung und wird daher verwendet:

Auflösen von Cousin-Abhängigkeiten mit der niedrigeren Version, die alle Einschränkungen erfüllt

Beachten Sie, dass sich die Pakete nicht auf dem gleichen Abstand befinden müssen, damit die Regel der Vetternabhängigkeiten angewendet werden kann. Im folgenden Diagramm wird "Package D 2.0.0" im Untergraphen "Paket C" ausgewählt, und "Package D 3.0.0" wird im Unterverzeichnis von Paket A ausgewählt. Im Unterdiagramm "Anwendung" gibt es keine direkte Abhängigkeit von Package D, sodass die niedrigste anwendbare Version Regel angewendet wird und Version 3.0.0 ausgewählt wird.

Auflösen von Cousin-Abhängigkeiten mit der niedrigeren Version, die alle Einschränkungen in verschiedenen Abständen erfüllt

In einigen Fällen ist es nicht möglich, alle Versionsanforderungen zu erfüllen. Wie unten dargestellt, erfordert Package A genau Package B 1.0.0 und Package C Package B >=2.0.0, dann kann NuGet die Abhängigkeiten nicht beheben und gibt einen Fehler.

Nicht aufgelöste Abhängigkeiten aufgrund einer genauen Versionsanforderung

In diesen Fällen sollte der Consumer der obersten Ebene (die Anwendung oder das Paket) eine eigene direkte Abhängigkeit von Paket B hinzufügen, sodass die Regel der direkten Abhängigkeit siegt.

Versionsbereiche und Vorabversionen mit PackageReference

Es ist nicht ungewöhnlich, dass von einem Paket sowohl stabile als auch Vorabversionen verfügbar sind. Beim Auflösen eines Abhängigkeitsdiagramms entscheidet NuGet, ob Vorabversionen für ein Paket basierend auf einer einzigen Regel berücksichtigt werden sollen: 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 der Praxis bedeutet dies unter der niedrigsten anwendbaren Regel Folgendes:

Versionsbereich Verfügbare Versionen Ausgewählte 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 Keine, NU1103 wird ausgelöst.
[1.0.0, 2.0.0-rc) 1.2.0-beta.1, 2.0.0-beta.3 1.2.0-beta.1

Abhängigkeitsauflösung mit packages.config

Mit packages.configwerden die Abhängigkeiten eines Projekts als flache Liste in packages.config geschrieben. Alle Abhängigkeiten dieser Pakete werden auch in derselben Liste geschrieben. Wenn Pakete installiert sind, ändert NuGet möglicherweise auch die .csproj Datei, app.config, web.configund andere einzelne Dateien.

Mit packages.configversucht NuGet, Abhängigkeitskonflikte während der Installation jedes einzelnen Pakets zu beheben. Wenn "Package A" installiert wird und von "Package B" abhängt und "Package B" bereits in packages.config als Abhängigkeit von etwas anderem aufgeführt ist, vergleicht NuGet die angeforderten Versionen von Package B und versucht, eine Version zu finden, die alle Versionsbeschränkungen erfüllt. Insbesondere wählt NuGet die untere major.minor Version aus, die Abhängigkeiten erfüllt.

Standardmäßig sucht NuGet 2.8 nach der niedrigsten Patchversion (siehe NuGet 2.8 Versionshinweise). Sie können diese Einstellung über das Attribut DependencyVersion in NuGet.Config sowie den Schalter -DependencyVersion in der Befehlszeile steuern.

Der packages.config Prozess zum Auflösen von Abhängigkeiten wird für größere Abhängigkeitsdiagramme kompliziert. Jede neue Paketinstallation erfordert eine Durchquerung des gesamten Diagramms und erhöht die Wahrscheinlichkeit für Versionskonflikte. Wenn ein Konflikt auftritt, wird die Installation beendet, wobei das Projekt in einem unbestimmten Zustand bleibt, insbesondere bei potenziellen Änderungen an der Projektdatei selbst. Dies ist kein Problem beim Verwenden anderer Paketverwaltungsformate.

Versionsbereiche und Vorabversionen mit packages.config

packages.config Auflösung erlaubt keine Vermischung von stabilen und vorab freigegebenen Abhängigkeiten in einem Graph. Wenn eine Abhängigkeit mit einem Bereich wie [1.0.0, 2.0.0)ausgedrückt wird, sind Vorabversionspakete im Diagramm nicht zulässig.

Verwalten von Abhängigkeitsressourcen

Wenn Sie das PackageReference-Format verwenden, können Sie steuern, welche Ressourcen aus Abhängigkeiten in das Projekt der obersten Ebene fließen. Ausführliche Informationen finden Sie in PackageReference.

Wenn das Projekt der obersten Ebene selbst ein Paket ist, haben Sie auch die Kontrolle über diesen Fluss, indem Sie die include und exclude Attribute mit Abhängigkeiten verwenden, die in der .nuspec Datei aufgeführt sind. Siehe .nuspec-Referenz - Abhängigkeiten.

Ausschließen von Referenzen

Es gibt Szenarien, in denen Assemblys mit demselben Namen in einem Projekt mehrmals referenziert werden können, wodurch Entwurfszeit- und Buildzeitfehler erzeugt werden. Betrachten Sie ein Projekt, das eine benutzerdefinierte Version von C.dllenthält, und verweist auf Package C, das auch C.dllenthält. Gleichzeitig hängt das Projekt auch von Package B ab, das auch von Package C und C.dllabhängt. Daher kann NuGet nicht bestimmen, welche C.dll verwendet werden sollen. Sie können jedoch nicht nur die Abhängigkeit des Projekts von Paket C entfernen, da Paket B ebenfalls davon abhängt.

Um dies zu beheben, müssen Sie direkt auf die gewünschte C.dll verweisen (oder ein anderes Paket verwenden, das auf die richtige verweist), und dann eine Abhängigkeit von Package C hinzufügen, die alle zugehörigen Ressourcen ausschließt. Dies erfolgt wie folgt, je nach verwendeter Paketverwaltungsformat:

  • PackageReference-: Fügen Sie ExcludeAssets="All" in die Abhängigkeit hinzu.

    <PackageReference Include="PackageC" Version="1.0.0" ExcludeAssets="All" />
    
  • packages.config: Entfernen Sie den Verweis auf PackageC aus der .csproj Datei, sodass nur auf die gewünschte Version von C.dll verwiesen wird.

Abhängigkeitsupdates während der Paketinstallation

Wenn eine Abhängigkeitsversion bereits erfüllt ist, wird die Abhängigkeit während anderer Paketinstallationen nicht aktualisiert. Ziehen Sie beispielsweise das Paket A in Betracht, das von Paket B abhängt, und gibt 1.0 für die Versionsnummer an. Das Quell-Repository enthält Die Versionen 1.0, 1.1 und 1.2 des Pakets B. Wenn A in einem Projekt installiert ist, das bereits B Version 1.0 enthält, wird B 1.0 weiterhin verwendet, da sie die Versionseinschränkung erfüllt. Wenn paket A jedoch Version 1.1 oder höher von B anfordert, wird B 1.2 installiert.

Beheben von inkompatiblen Paketfehlern

Während eines Paketwiederherstellungsvorgangs wird möglicherweise der Fehler "Mindestens ein Paket ist nicht kompatibel..." angezeigt. oder dass ein Paket mit dem Zielframework des Projekts "nicht kompatibel" ist.

Dieser Fehler tritt auf, wenn mindestens eines der Pakete, auf die in Ihrem Projekt verwiesen wird, nicht darauf hinweist, dass sie das Zielframework des Projekts unterstützen. d. h., das Paket enthält keine geeignete DLL in seinem lib Ordner für ein Zielframework, das mit dem Projekt kompatibel ist. (Eine Liste finden Sie unter Ziel-Frameworks.)

Wenn ein Projekt z. B. auf netstandard1.6 ausgerichtet ist und Sie versuchen, ein Paket zu installieren, das DLLs nur in den Ordnern lib\net20 und \lib\net45 enthält, werden Meldungen wie die folgenden für das Paket und möglicherweise seine Nachfolger angezeigt:

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

Führen Sie eine der folgenden Aktionen aus, um Inkompatibilitäten zu beheben:

  • Richten Sie Ihr Projekt auf ein Framework aus, das von den Paketen unterstützt wird, die Sie verwenden möchten.
  • Wenden Sie sich an den Autor der Pakete, und arbeiten Sie mit ihnen zusammen, um Unterstützung für Ihr ausgewähltes Framework hinzuzufügen. Jede Paketauflistungsseite auf nuget.org verfügt zu diesem Zweck über einen Link Kontaktieren Sie die Eigentümer.

Trinkgeld

Alternative Lösung: NuGetSolver ist eine von Microsoft DevLabs entwickelte Visual Studio-Erweiterung, die zur Lösung von Abhängigkeitskonflikten entwickelt wurde. Es automatisiert den Prozess der Identifizierung und Behebung dieser Probleme. Weitere Details finden Sie auf der Seite NuGetSolver auf dem Visual Studio Marketplace, und wir freuen uns, Ihr Feedback zu Ihrer Erfahrung zu hören.