Wie genau funktioniert die Eigenschaft "Spezifische Version" einer Assemblyreferenz in Visual Studio?

155

Heute habe ich mir die Eigenschaft "Spezifische Version" von Baugruppenreferenzen in Visual Studio 2010 genauer angesehen. Nach einigen Experimenten mit unerwarteten Ergebnissen wollte ich so viel wie möglich über die Funktionsweise der Eigenschaft erfahren. Selbst SO, so scheint es mir, hat nicht alle Antworten. Hier ist mein Versuch, die Frage selbst zu beantworten:

Wie genau funktioniert die Eigenschaft "Spezifische Version" einer Assemblyreferenz in Visual Studio?

herzbube
quelle

Antworten:

254

Es ist eine Eigenschaft zur Kompilierungszeit!

Eines der wichtigsten Dinge, die Sie wissen müssen, ist, dass "Spezifische Version" eine Eigenschaft ist, die zur Kompilierungszeit und nicht zur Laufzeit wirksam wird .

Worum geht es?

Wenn ein Projekt erstellt wird, müssen die Assemblyreferenzen des Projekts aufgelöst werden, um die physischen Assemblys zu finden, die das Buildsystem verwenden sollte. Wenn die Prüfung "Spezifische Version" durchgeführt wird (siehe Abschnitt "Wann wird" Spezifische Version "geprüft?"), Beeinflusst dies das Ergebnis des Assembly-Auflösungsprozesses:

  • Das Build-System findet eine physische Assembly, die es möglicherweise verwenden kann
  • Das Build-System vergleicht die Version der physischen Assembly mit der Assembly-Version, die in der .csproj-Datei für die Assembly-Referenz gespeichert ist
  • Wenn die beiden Assemblyversionen genau identisch sind, ist der Auflösungsprozess erfolgreich und die gefundene physische Assembly wird für den Build verwendet
  • Wenn die beiden Baugruppenversionen nicht übereinstimmen, wird die physische Baugruppe verworfen und der Auflösungsprozess wird fortgesetzt, indem die nächste potenzielle Baugruppe gesucht wird
  • Wenn keine potenziellen physischen Baugruppen mehr gefunden werden können, schlägt der Auflösungsprozess fehl. Dies führt zu einer Compiler-Warnung (Warnung MSB3245), die Sie darüber informiert, dass die Referenz nicht aufgelöst werden konnte.
  • Interessanterweise geht der Build dann weiter! Wenn der Code keine tatsächlichen Verweise auf die Assembly enthält, ist der Build erfolgreich (mit der zuvor erwähnten Warnung). Wenn der Code Verweise enthält, schlägt der Build mit einem Fehler fehl, der aussieht, als würde der Code unbekannte Typen oder Namespaces verwenden. Der einzige Hinweis, warum der Build wirklich fehlgeschlagen ist, ist die Warnung MSB3245.

Reihenfolge, in der Baugruppen aufgelöst werden

Die Reihenfolge, in der der Baugruppenauflösungsprozess potenzielle Baugruppen findet, scheint folgende zu sein:

  1. Die Assembly, auf die das <HintPath>Element in der .csproj-Datei verweist
  2. Der Projektausgabepfad
  3. Der GAC

Beachten Sie, dass der Auflösungsprozess zunächst versucht, die Assembly mit der höchsten Version aufzulösen, wenn im GAC mehrere Versionen der Assembly vorhanden sind. Dies ist nur wichtig, wenn die Prüfung "Spezifische Version" nicht durchgeführt wird.

Wann wird "Spezifische Version" aktiviert?

Visual Studio stützt seine Entscheidung, ob die Prüfung "Spezifische Version" durchgeführt werden soll, auf zwei Informationen, die in der .csproj-Datei enthalten sind:

  • Das Vorhandensein oder Fehlen des <SpecificVersion>Elements und sein Wert (falls vorhanden)
  • Das Vorhandensein oder Fehlen von Versionsinformationen in der Baugruppenreferenz

So sieht eine typische Assemblyreferenz mit Versionsinformationen aus:

<Reference Include="Foo, Version=1.2.3.4, Culture=neutral, processorArchitecture=MSIL">
  <SpecificVersion>True</SpecificVersion>
  <HintPath>..\..\Bar\Foo.dll</HintPath>
</Reference>

Und so sieht die Assemblyreferenz ohne Versionsinformationen aus:

<Reference Include="Foo">
[...]

Die folgende Tabelle zeigt, wann die Prüfung "Spezifische Version" durchgeführt wird und wann nicht.

                            |     Version information
                            |  Present       Not present
----------------------------+------------------------------
<SpecificVersion>           |
- Present, has value True   |    Yes (1)        Yes (check always fails) (2)
- Present, has value False  |    No  (3)        No (4)
- Not present               |    Yes (5)        No (6)

Das Überraschende dabei ist, dass keine Überprüfung durchgeführt wird, wenn sowohl <SpecificVersion>als auch Versionsinformationen fehlen (Fall 6). Ich hätte erwartet, dass die Prüfung durchgeführt wird und immer fehlschlägt (wie in Fall 2), da nach meinem Verständnis das Fehlen von <SpecificVersion>den Standardwert "True" impliziert. Dies ist möglicherweise eine Besonderheit von Visual Studio 2010, in dem ich meine Tests durchgeführt habe.

Wenn Sie die Eigenschaften einer Assemblyreferenz in der Visual Studio-Benutzeroberfläche untersuchen (wählen Sie die Referenz aus und drücken Sie F4), gibt der Wert, den Sie für die Eigenschaft "Bestimmte Version" sehen, an, ob Visual Studio die "Bestimmte Version" ausführen wird oder nicht. prüfen. In Fall 6 zeigt die Benutzeroberfläche "True" an, obwohl das <SpecificVersion>Element in der .csproj-Datei nicht vorhanden ist.

Nebenwirkungen von "Lokal kopieren"

Wenn die Eigenschaft "Lokal kopieren" auf "True" gesetzt ist, der Assemblyauflösungsprozess jedoch aufgrund der Prüfung "Spezifische Version" fehlschlägt, wird keine Assembly kopiert.

Referenzmaterial

herzbube
quelle
Danke für das Detail. Kann ich nur überprüfen ... Die Überprüfung der Baugruppenversion erfolgt nur für Baugruppen mit starken Namen. ist das richtig? Wenn wir über das Überprüfen der Version einer Assembly sprechen, erfolgt dies durch Vergleichen des Namens der Assembly, auf die verwiesen wird ? (Im Fall einer Assembly mit starkem Namen enthält dieser Name die Versionsinformationen, sodass nicht wie in einem separaten Versionsfeld geprüft wird?)
Gavin Hope
2
@GavinHope Frage 1: Nein, die Versionsprüfung ist nicht auf starke Namen beschränkt, hauptsächlich weil ein Assemblyname die Version enthalten kann, aber immer noch kein starker Name ist (z. B. wenn das PublicKeyToken=Teil fehlt ). Wenn Sie die Tabelle gegen Ende meines Beitrags überprüfen, können Sie auch feststellen, dass die Versionsprüfung auch dann erfolgen kann, wenn das Version=Teil im Assemblynamen in der .csproj fehlt. Frage 2: Ich gehe davon aus, dass der Assemblyname für den Vergleich verwendet wird, ja. Ich würde keine andere Quelle für die Informationen kennen.
Herzbube
"In Fall 6 zeigt die Benutzeroberfläche" True "an, obwohl das Element <SpecificVersion> in der .csproj-Datei nicht vorhanden ist." - Es scheint, dass der Standardwert True ist . Nach dem Umschalten der spezifischen Version in der Benutzeroberfläche auf True wurde das <SpecificVersion>Tag vollständig weggelassen, das zuvor den Wert False hatte .
Samis
@herzbube - Ich denke, die Bedeutung von "Bestimmte Version" im Fenster "Visual Studio> Projekteigenschaften" ist das Gegenteil von dem, was Sie hier sagen (was das Gegenteil von dem ist, was Sie erwarten würden). Laut Visual Studio gibt der Wert (true oder false) von "Bestimmte Version" "an, ob diese Assembly ohne Berücksichtigung von Multi-Targeting-Regeln für die Assemblyauflösung aufgelöst werden kann".
N73k
35

Wenn Sie eine Referenz hinzufügen, zeichnet Visual Studio die [AssemblyVersion] der Assembly in der Projektdatei auf. Das ist wichtig. Wenn Sie beispielsweise ein Jahr später eine Fehlerbehebung erstellen, möchten Sie sicherstellen, dass Sie das Projekt mit genau derselben Version der Referenz neu erstellen, damit es sich um ein echtes Drop-In handelt. Sie erhalten eine Fehlermeldung, wenn sich die Referenzbaugruppe geändert hat.

Das ist aber nicht immer wünschenswert. Einige Programmierer lassen die Assembly-Version automatisch inkrementieren und generieren bei jeder Neuerstellung eine neue Version. Auch wenn sich die öffentliche Schnittstelle der Assembly nie geändert hat. Einige konfigurieren ihr Projekt mithilfe von Nuget, um Bibliotheken abzurufen, und lassen es die Bibliothek automatisch aktualisieren, wenn eine neue Version verfügbar ist. Sie möchten die Eigenschaft "Spezifische Version" auf "Falsch" setzen, um den Kompilierungsfehler zu unterdrücken.

Um die Konsequenzen zu verstehen, müssen Sie den gesamten Build des Programms neu bereitstellen, um Unfälle zu vermeiden. Versionsinkongruenzen zur Laufzeit stürzen das Programm ab und können nur mit einer <bindingRedirect>in der .config-Datei unterdrückten Datei unterdrückt werden .

Hans Passant
quelle
2
Vielen Dank für die Information, warum "Spezifische Version" wichtig ist. Dies ist ein guter Begleiter zu den rein mechanischen Aspekten, die ich in meiner Antwort behandele.
Herzbube
@Hans Passant - Ist Ihr letzter Absatz für SpecificVersion True oder False gültig? Ich denke, das sind die Konsequenzen, wenn Sie es auf wahr setzen.
GreenEyedAndy
1
SpecificVersion gilt nur für die Erstellung Ihrer App. Zur Laufzeit besteht die CLR immer auf einer genauen Übereinstimmung mit der Versionsnummer der Referenzbaugruppe. Wenn Sie zur Erstellungszeit eine neuere Version verwendet haben, muss diese auch zur Laufzeit diese neuere Version sein.
Hans Passant
1
Vorsicht vor VS2013 & .Net 4.5.1 AutoGenerateBindingRedirects Sie können die DLL-Bindung auf eine neuere Version umleiten, obwohl Sie ihr gesagt haben, dass sie eine bestimmte Version verwenden soll
Dennis Kuypers
1
@HansPassant Ich dachte, die CLR berücksichtigt dies nicht, [AssemblyVersion]wenn Assemblys keinen starken Namen haben.
tm1