Come funziona esattamente la proprietà "Versione specifica" di un riferimento di assembly in Visual Studio?


156

Oggi ho esaminato più da vicino la proprietà "Versione specifica" dei riferimenti di assembly in Visual Studio 2010. Dopo alcuni esperimenti con risultati imprevisti, ho iniziato a imparare il più possibile sul funzionamento della proprietà. Anche così, mi sembra, non ha tutte le risposte, quindi ecco il mio tentativo di auto-rispondere alla domanda:

Come funziona esattamente la proprietà "Versione specifica" di un riferimento di assembly in Visual Studio?

Risposte:


255

È una proprietà in fase di compilazione!

Una delle cose più importanti da sapere è che "Versione specifica" è una proprietà che ha effetto in fase di compilazione e non in fase di esecuzione.

Cos'è tutto questo?

Quando viene creato un progetto, i riferimenti di assieme del progetto devono essere risolti al fine di trovare gli assiemi fisici che il sistema di generazione dovrebbe usare. Se viene eseguito il controllo "Versione specifica" (vedere la sezione "Quando è selezionata la" Versione specifica "?"), Influisce sul risultato del processo di risoluzione dell'assembly:

  • Il sistema di generazione individua un assembly fisico che può potenzialmente utilizzare
  • Il sistema di generazione confronta la versione dell'assembly fisico con la versione dell'assembly memorizzata nel file .csproj per il riferimento dell'assembly
  • Se le due versioni dell'assieme sono esattamente le stesse, il processo di risoluzione ha esito positivo e l'assemblaggio fisico trovato viene utilizzato per la compilazione
  • Se le due versioni dell'assembly non corrispondono, l'assemblaggio fisico viene scartato e il processo di risoluzione continua individuando l'assembly potenziale successivo
  • Se non è possibile individuare più potenziali assiemi fisici, il processo di risoluzione non riesce. Ciò provoca un avviso del compilatore (avviso MSB3245) che indica che non è stato possibile risolvere il riferimento.
  • È interessante notare che la build continua quindi! Se il codice non ha riferimenti effettivi all'assembly, la compilazione ha esito positivo (con l'avviso precedentemente citato). Se il codice ha riferimenti, la compilazione fallisce con un errore che sembra che il codice stia usando tipi o spazi dei nomi sconosciuti. L'unica indicazione per cui la build veramente fallito è il MSB3245 avvertimento.

Ordine in cui vengono risolti gli assiemi

L'ordine in cui il processo di risoluzione degli assembly individua i potenziali assembly sembra essere questo:

  1. L'assembly a cui fa riferimento l' <HintPath>elemento nel file .csproj
  2. Il percorso di output del progetto
  3. Il GAC

Notare che se nel GAC esistono diverse versioni dell'assembly, il processo di risoluzione tenta innanzitutto di risolvere l'assembly con la versione più alta. Questo è importante solo se il controllo "Versione specifica" non viene eseguito.

Quando viene selezionata la "Versione specifica"?

Visual Studio basa la sua decisione sull'esecuzione del controllo "Versione specifica" su due informazioni contenute nel file .csproj:

  • La presenza o l'assenza <SpecificVersion>dell'elemento e il suo valore (se presente)
  • La presenza o l'assenza di informazioni sulla versione nel riferimento dell'assembly

Ecco come appare un tipico riferimento di assieme con le informazioni sulla versione:

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

Ecco come appare il riferimento all'assemblaggio senza le informazioni sulla versione:

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

La tabella seguente mostra quando viene eseguito il controllo "Versione specifica" e quando non lo è.

                            |     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)

La cosa sorprendente qui è che non viene eseguito alcun controllo se entrambe <SpecificVersion>e le informazioni sulla versione sono assenti (caso 6). Mi sarei aspettato che il controllo venisse eseguito e fallisse sempre (come nel caso 2) perché nella mia comprensione l'assenza di <SpecificVersion>implica il valore predefinito "Vero". Questa potrebbe essere una stranezza di Visual Studio 2010 in cui ho eseguito i miei test.

Quando si esaminano le proprietà di un riferimento di assembly nell'interfaccia utente di Visual Studio (selezionare il riferimento e premere F4), il valore visualizzato per la proprietà "Versione specifica" indica se Visual Studio eseguirà o meno la "Versione specifica" dai un'occhiata. Nel caso 6 l'interfaccia utente mostrerà "True", sebbene l' <SpecificVersion>elemento non sia presente nel file .csproj.

Effetti collaterali su "Copia locale"

Se la proprietà "Copia locale" è impostata su "True" ma il processo di risoluzione dell'assembly non riesce a causa del controllo "Versione specifica", nessun assembly viene copiato.

Materiale di riferimento


Grazie per il dettaglio Posso solo controllare ... Il controllo della versione dell'assembly si verifica solo per gli assembly con nomi sicuri; è giusto? Inoltre, quando parliamo di controllare la versione di un assembly, viene fatto confrontando il nome dell'assembly di riferimento ? (Nel caso di un assembly con nome sicuro, quel nome include le informazioni sulla versione, quindi non è come se fosse controllato un campo versione separato?)
Gavin Hope

2
@GavinHope Domanda 1: No, il controllo della versione non si limita ai nomi sicuri, principalmente perché un nome di assembly può includere la versione ma non essere comunque un nome sicuro (ad esempio se manca la PublicKeyToken=parte). Inoltre, se controlli la tabella verso la fine del mio post, puoi vedere che può verificarsi il controllo della versione anche se la Version=parte manca dal nome dell'assembly nel file .csproj. Domanda 2: suppongo che il nome dell'assembly sia usato per il confronto, sì. Non saprei di nessun'altra fonte per l'informazione.
Herzbube,

"Nel caso 6 l'interfaccia utente mostrerà" True ", sebbene l'elemento <SpecificVersion> non sia presente nel file .csproj." - Sembra che il valore predefinito sia True . Dopo aver impostato Versione specifica nell'interfaccia utente su True, il <SpecificVersion>tag è stato completamente omesso, che in precedenza aveva un valore False .
Samis,

@herzbube - Penso che il significato di "Versione specifica" nella finestra di Visual Studio> Proprietà progetto sia l'opposto di quello che stai dicendo qui (che è l'opposto di quello che ti aspetteresti). Visual Studio dice che il valore (vero o falso) di "versione specifica" "indica se questa assemblea può essere risolto senza riguardo alla multi-target regole per la risoluzione di montaggio".
N73k,

35

Quando si aggiunge un riferimento, Visual Studio registra [AssemblyVersion] dell'assembly nel file di progetto. Questo è importante. Se, ad esempio, creare un bug fix, un anno dopo poi si vuole fare in modo che si ricostruisce il progetto con la esatta stessa versione di riferimento ed è quindi un vero e drop-in. Verrà visualizzato un errore se l'assembly di riferimento è stato modificato.

Ma questo non è sempre desiderabile. Alcuni programmatori consentono alla versione dell'assemblaggio di aumentare automaticamente, generando una nuova versione ogni volta che ricostruiscono. Anche se l'interfaccia pubblica dell'assemblea non è mai cambiata. Alcuni configurano il loro progetto usando Nuget per ottenere librerie e lasciarlo aggiornare automaticamente quando è disponibile una nuova versione. Vorranno impostare la proprietà Versione specifica su False per eliminare l'errore di compilazione.

Abbastanza importante per capire le conseguenze, è necessario ridistribuire l'intera build del programma per evitare incidenti. La versione non corrisponde al crash durante l'esecuzione del programma e può essere eliminata solo con un <bindingRedirect>file .config che è rischioso.


2
Grazie per le informazioni sul motivo per cui "Versione specifica" è importante, questo è un buon compagno per gli aspetti puramente meccanici che sto affrontando nella mia risposta.
Herzbube,

@Hans Passant: il tuo ultimo paragrafo è valido per SpecificVersion True o False? Penso che queste siano le conseguenze quando lo imposti su true.
GreenEyedAndy,

1
SpecificVersion si applica solo alla creazione della tua app. In fase di esecuzione il CLR insiste sempre su una corrispondenza esatta con il numero di versione dell'assieme di riferimento. Se hai utilizzato una versione più recente al momento della creazione, deve essere anche quella versione più recente in fase di esecuzione.
Hans Passant,

1
Attenzione a VS2013 e .Net 4.5.1 AutoGenerateBindingRedirects Potrebbero reindirizzare il binding della dll a una versione più recente anche se gli hai detto di utilizzare una versione specifica
Dennis Kuypers,

1
@HansPassant Pensavo che il CLR non prendesse in considerazione [AssemblyVersion]quando gli assembly non hanno un nome sicuro .
tm1
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.