Como exatamente a propriedade "Versão específica" de uma referência de montagem funciona no Visual Studio?

156

Hoje, observei mais detalhadamente a propriedade "Versão específica" das referências de montagem no Visual Studio 2010. Após algumas experiências com resultados inesperados, decidi aprender o máximo possível sobre como a propriedade funciona. Mesmo SO, ao que me parece, não tem todas as respostas, então aqui está minha tentativa de responder a pergunta:

Como exatamente a propriedade "Versão específica" de uma referência de montagem funciona no Visual Studio?

herzbube
fonte

Respostas:

255

É uma propriedade em tempo de compilação!

Uma das coisas mais importantes a saber é que "Versão específica" é uma propriedade que entra em vigor no tempo de compilação e não no tempo de execução.

Sobre o que é tudo isso?

Quando um projeto é construído, as referências de montagem do projeto precisam ser resolvidas para encontrar os assemblies físicos que o sistema de construção deve usar. Se a verificação "Versão específica" for executada (consulte a seção "Quando a" Versão específica "é marcada?"), Ela afeta o resultado do processo de resolução da montagem:

  • O sistema de construção localiza um conjunto físico que ele pode potencialmente usar
  • O sistema de compilação compara a versão da montagem física com a versão da montagem armazenada no arquivo .csproj para a referência de montagem
  • Se as duas versões da montagem forem exatamente iguais, o processo de resolução será bem-sucedido e a montagem física encontrada será usada para a compilação
  • Se as duas versões da montagem não corresponderem, a montagem física será descartada e o processo de resolução continuará localizando a próxima montagem em potencial
  • Se não for possível localizar mais assemblies físicos em potencial, o processo de resolução falhará. Isso resulta em um aviso do compilador (aviso MSB3245) que informa que a referência não pôde ser resolvida.
  • Curiosamente, a construção continua! Se o código não tiver referências reais ao assembly, a compilação será bem-sucedida (com o aviso mencionado anteriormente). Se o código tiver referências, a compilação falhará com um erro que parece que o código estava usando tipos ou espaços de nomes desconhecidos. A única indicação do motivo pelo qual a compilação realmente falhou é o aviso MSB3245.

Ordem na qual as montagens são resolvidas

A ordem na qual o processo de resolução da montagem localiza as montagens em potencial parece ser a seguinte:

  1. A montagem referenciada pelo <HintPath>elemento no arquivo .csproj
  2. O caminho de saída do projeto
  3. O GAC

Observe que, se existirem várias versões do assembly no GAC, o processo de resolução primeiro tenta resolver o assembly com a versão mais alta. Isso é importante apenas se a verificação "Versão específica" não for feita.

Quando a "Versão específica" está marcada?

O Visual Studio baseia sua decisão de executar a verificação "Versão específica" em duas informações encontradas no arquivo .csproj:

  • A presença ou ausência do <SpecificVersion>elemento e seu valor (se houver)
  • A presença ou ausência de informações de versão na referência de montagem

É assim que uma referência típica de montagem com informações de versão se parece:

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

E é assim que a referência de montagem se parece sem informações de versão:

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

A tabela a seguir mostra quando a verificação "Versão específica" é executada e quando não é.

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

O surpreendente aqui é que nenhuma verificação será realizada se as <SpecificVersion>informações de versão e de versão estiverem ausentes (caso 6). Eu esperava que a verificação fosse realizada e sempre falhasse (igual ao caso 2) porque, no meu entendimento, a ausência de <SpecificVersion>implica o valor padrão "True". Isso pode ser uma peculiaridade do Visual Studio 2010, onde eu fiz meus testes.

Ao examinar as propriedades de uma referência de montagem na interface do usuário do Visual Studio (selecione a referência e pressione F4), o valor que você vê para a propriedade "Versão específica" informa se o Visual Studio executará ou não a "Versão específica" Verifica. No caso 6, a interface do usuário mostrará "True", embora o <SpecificVersion>elemento não esteja presente no arquivo .csproj.

Efeitos colaterais em "Copiar local"

Se a propriedade "Copiar local" estiver definida como "Verdadeiro", mas o processo de resolução da montagem falhar devido à verificação "Versão específica", nenhuma montagem será copiada.

Material de referência

herzbube
fonte
Obrigado pelo detalhe. Posso apenas verificar ... a verificação da versão da montagem só acontece para montagens com nomes fortes; Isso está certo? Além disso, quando falamos em verificar a versão de uma montagem - isso é feito comparando o nome da montagem referenciada ? (No caso de um de nome forte assembly, esse nome inclui as informações de versão, então não é como um campo versão separada é verificada?)
Gavin Esperança
2
@GavinHope Pergunta 1: Não, a verificação de versão não se limita a nomes fortes, principalmente porque um nome de montagem pode incluir a versão, mas ainda não é um nome forte (por exemplo, se estiver faltando a PublicKeyToken=peça). Além disso, se você verificar a tabela no final da minha postagem, poderá ver que a verificação da versão pode ocorrer mesmo se a Version=peça estiver faltando no nome da montagem no .csproj. Pergunta 2: Suponho que o nome do assembly seja usado para a comparação, sim. Eu não conheceria nenhuma outra fonte de informação.
herzbube
"No caso 6, a interface do usuário mostrará" True ", embora o elemento <SpecificVersion> não esteja presente no arquivo .csproj." - Parece que o valor padrão é True . Após alternar a versão específica na interface do usuário para True, a <SpecificVersion>tag foi completamente omitida, que anteriormente possuía o valor False .
samis 19/09/18
@herzbube - acho que o significado de "Versão específica" na janela Visual Studio> Propriedades do projeto é o oposto do que você está dizendo aqui (o oposto do que você esperaria). O Visual Studio diz que o valor (verdadeiro ou falso) da "Versão específica" "indica se esse assembly pode ser resolvido sem levar em consideração as regras de vários destinos para a resolução do assembly".
N73k 11/04/19
35

Quando você adiciona uma referência, o Visual Studio registra a [AssemblyVersion] da montagem no arquivo de projeto. Isso é importante. Se você, por exemplo, criar uma correção de bug um ano depois, deseja garantir que você reconstrua o projeto com a mesma versão exata da referência, para que seja um verdadeiro exemplo. Você receberá um erro se o assembly de referência foi alterado.

Mas isso nem sempre é desejável. Alguns programadores permitem que a versão do assembly seja incrementada automaticamente, gerando uma nova versão toda vez que eles são reconstruídos. Mesmo que a interface pública da montagem nunca tenha mudado. Alguns configuram seu projeto usando o Nuget para obter bibliotecas e permitem que ele atualize automaticamente a biblioteca quando houver uma nova versão disponível. Eles gostariam de definir a propriedade Versão específica como Falso para suprimir o erro de compilação.

Muito importante para entender a conseqüência, você precisa reimplementar toda a compilação do programa para evitar acidentes. As incompatibilidades de versão no tempo de execução interrompem o programa e só podem ser suprimidas com um <bindingRedirect>no arquivo .config, o que é arriscado.

Hans Passant
fonte
2
Obrigado pela informação por que a "Versão específica" é importante, este é um bom companheiro para os aspectos puramente mecânicos que estou abordando na minha resposta.
precisa saber é o seguinte
@ Hans Passant - seu último parágrafo é válido para SpecificVersion True ou False? Eu acho que essas são as consequências quando você define como verdadeiro.
GreenEyedAndy 27/10
1
A SpecificVersion se aplica apenas à criação do seu aplicativo. No tempo de execução, o CLR sempre insiste em uma correspondência exata com o número da versão do assembly de referência. Se você usou uma versão mais nova no momento da construção, ela também deve ser a versão mais nova no tempo de execução.
Hans Passant
1
Cuidado com o VS2013 e o .Net 4.5.1 AutoGenerateBindingRedirects Eles podem redirecionar a associação de dll para uma versão mais recente, mesmo que você tenha dito para usar uma versão específica
Dennis Kuypers
1
@HansPassant Eu pensei que o CLR não leva em consideração [AssemblyVersion]quando as assembléias não têm um nome forte assinado.
TM1