Partilhar via


Redirecionar versões de montagem

Observação

Este artigo é específico do .NET Framework. Não se aplica a implementações mais recentes do .NET, incluindo o .NET 6 e versões posteriores.

Pode redirecionar referências de ligação em tempo de compilação para assemblies do .NET Framework, assemblies de terceiros ou assemblies da sua própria aplicação. Você pode redirecionar seu aplicativo para usar uma versão diferente de um assembly de várias maneiras: por meio da política do editor, de um arquivo de configuração do aplicativo ou do arquivo de configuração da máquina. Este artigo discute como funciona a assembly binding no .NET Framework e como pode configurá-la.

Dica

Este artigo é específico para aplicações do .NET Framework. Para informações sobre o carregamento de assemblies no .NET 5+ (e .NET Core), veja Carregamento de dependências em .NET.

Unificação de assemblagem e vinculação padrão

Os bindings para assemblies do .NET Framework são por vezes redirecionados através de um processo chamado unificação do assembly. O .NET Framework consiste numa versão do runtime da linguagem comum e cerca de duas dezenas de assemblies do .NET Framework que compõem a biblioteca de tipos. Estas assemblies do .NET Framework são tratadas pelo runtime como uma única unidade. Por defeito, quando uma aplicação é lançada, todas as referências a tipos de código executados pelo runtime são direcionadas para assemblies do .NET Framework que têm o mesmo número de versão do runtime carregado num processo. Os redirecionamentos que ocorrem com esse modelo são o comportamento padrão para o tempo de execução.

Por exemplo, se a sua aplicação faz referência a tipos no espaço de nomes System.XML e foi construída usando .NET Framework 4.5, contém referências estáticas ao assembly System.XML que vem com a versão 4.5 de runtime. Se quiseres redirecionar a referência de ligação para apontar para o assembly System.XML que vem com .NET Framework 4, podes colocar a informação de redirecionamento no ficheiro de configuração da app. Um redirecionamento de binding num ficheiro de configuração para uma assemblagem unificada do .NET Framework resulta na anulação da unificação para essa assemblagem.

Além disso, talvez você queira redirecionar manualmente a vinculação de assembly para assemblies de terceiros se houver várias versões disponíveis.

Dica

Se você atualizar um pacote NuGet ao qual seu aplicativo faz referência indiretamente e começar a ver novos erros, como FileLoadException, MissingMethodException, TypeLoadExceptionou FileNotFoundException, talvez seja necessário habilitar redirecionamentos de vinculação automática ou adicionar manualmente um redirecionamento de vinculação. Isso é normal ao atualizar pacotes NuGet e é resultado de alguns pacotes serem criados em relação a uma versão mais antiga de uma dependência. O seguinte trecho do ficheiro de configuração da aplicação adiciona um redirecionamento de vinculação para o pacote System.Memory:

<dependentAssembly>
   <assemblyIdentity name="System.Memory" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
   <bindingRedirect oldVersion="0.0.0.0-4.0.2.0" newVersion="4.0.2.0" />
</dependentAssembly>

Redirecionar versões usando a política do editor

Os fornecedores de componentes podem direcionar os aplicativos para uma versão mais recente de um componente incluindo um ficheiro de política do editor com o novo componente. O ficheiro de política do editor, que está localizado no cache global de montagem, contém configurações de redirecionamento de montagem.

Cada versão principal.versão secundária de um assembly tem o seu próprio arquivo de política do editor. Por exemplo, redirecionamentos da versão 2.0.2.222 para 2.0.3.000 e da versão 2.0.2.321 para a versão 2.0.3.000 vão para o mesmo arquivo, porque estão associados à versão 2.0. No entanto, um redirecionamento da versão 3.0.0.999 para a versão 4.0.0.000 é inserido no arquivo da versão 3.0.0.999. Cada versão principal do .NET Framework tem o seu próprio ficheiro de política de publicador.

Caso exista um ficheiro de política do publicador para um assembly, o tempo de execução verificará esse ficheiro depois de verificar o manifesto do assembly e o ficheiro de configuração da aplicação. Os fornecedores devem usar arquivos de política do editor somente quando o novo assembly for retrocompatível com o assembly que está sendo redirecionado.

Você pode ignorar a política do editor para seu aplicativo especificando as configurações no arquivo de configuração do aplicativo, conforme discutido na seção Ignorar política do editor.

Redirecionar versões no nível do aplicativo

Existem algumas técnicas diferentes para alterar o comportamento de associação para seu aplicativo por meio do arquivo de configuração do aplicativo: você pode editar manualmente o arquivo, pode confiar no redirecionamento de vinculação automáticoou pode especificar o comportamento de vinculação ignorando de política do editor.

Editar manualmente o arquivo de configuração do aplicativo

Você pode editar manualmente o arquivo de configuração do aplicativo para resolver problemas de montagem. Por exemplo, se um fornecedor lançar uma versão mais recente de um *assembly* que a sua aplicação usa sem fornecer uma política do editor (porque eles não garantem compatibilidade com versões anteriores), poderá direcionar a sua aplicação para usar a versão mais recente do *assembly* inserindo as informações de vinculação do *assembly* no ficheiro de configuração da aplicação da seguinte forma.

<dependentAssembly>
  <assemblyIdentity name="someAssembly"
    publicKeyToken="32ab4ba45e0a69a1"
    culture="en-us" />
  <bindingRedirect oldVersion="7.0.0.0" newVersion="8.0.0.0" />
</dependentAssembly>

Confie no redirecionamento automático de vinculação

Quando crias uma aplicação de ambiente de trabalho no Visual Studio que visa o .NET Framework 4.5.1 ou uma versão posterior, a aplicação usa redirecionamento automático de binding. Isso significa que, se dois componentes fizerem referência a versões diferentes do mesmo assembly de nome forte, o tempo de execução adicionará automaticamente um redirecionamento de vinculação à versão mais recente do assembly no arquivo de configuração do aplicativo de saída (app.config). Esse redirecionamento substitui a unificação da assembleia que, de outra forma, poderia ocorrer. O arquivo app.config de origem não é modificado. Por exemplo, digamos que a sua aplicação faz referência direta a um componente .NET Framework fora de banda, mas usa uma biblioteca de terceiros que visa uma versão mais antiga do mesmo componente. Quando você compila o aplicativo, o arquivo de configuração do aplicativo de saída é modificado para conter um redirecionamento de vinculação para a versão mais recente do componente.

Se você criar um aplicativo Web, receberá um aviso de compilação sobre o conflito de vinculação, que, por sua vez, lhe dará a opção de adicionar o redirecionamento de vinculação necessário ao arquivo de configuração da Web de origem.

Se adicionares manualmente redirecionamentos de binding ao ficheiro de app.config de origem, em tempo de compilação, Visual Studio tenta unificar os assemblies com base nos redirecionamentos de binding que adicionaste. Por exemplo, digamos que você insira o seguinte redirecionamento de vinculação para um assembly:

<bindingRedirect oldVersion="3.0.0.0" newVersion="2.0.0.0" />

Se outro projeto em seu aplicativo fizer referência à versão 1.0.0.0 do mesmo assembly, o redirecionamento automático de vinculação adicionará a seguinte entrada ao arquivo de app.config de saída para que o aplicativo seja unificado na versão 2.0.0.0 desse assembly:

<bindingRedirect oldVersion="1.0.0.0" newVersion="2.0.0.0" />

Pode ativar o redirecionamento automático de binding caso a sua aplicação tenha como alvo versões mais antigas do .NET Framework. Você pode substituir este comportamento predefinido fornecendo informações de redirecionamento de associação no arquivo app.config para qualquer assembly ou desligando o recurso de redirecionamento de associação. Para obter informações sobre como ativar ou desativar esse recurso, consulte Como ativar e desativar o redirecionamento automático de vinculação.

Ignorar a política do editor

Você pode substituir a política do editor no arquivo de configuração do aplicativo, se necessário. Por exemplo, novas versões de assemblies que alegam ser compatíveis com versões anteriores ainda podem causar falhas numa aplicação. Se quiseres ignorar a política do editor, adiciona um elemento <publisherPolicy> ao elemento <dependentAssembly> no ficheiro de configuração da aplicação e define o atributo apply como no, o que substitui todas as configurações de yes anteriores.

<publisherPolicy apply="no" />

Ignore a política do editor para manter seu aplicativo em execução para seus usuários, mas certifique-se de relatar o problema ao fornecedor do assembly. Se um conjunto tiver um ficheiro de política do editor, o fornecedor deve certificar-se de que o conjunto é compatível com versões anteriores e que os clientes possam usar ao máximo a nova versão.

Redirecionar versões para testes, plug-ins ou bibliotecas usadas por outro componente

Para testes, você deve gerar um arquivo .dll.config. A maioria das estruturas de teste de unidade existentes honram esses arquivos ao carregar testes.

Plugins podem suportar os arquivos .dll.config, no entanto, eles podem também não o fazer. O único mecanismo infalível para redirecionamentos é fornecendo bindingRedirects quando o AppDomain é criado.

Você pode tentar resolver esse problema com manipuladores de eventos AssemblyResolve, mas isso não funciona, pois esses manipuladores só são chamados em uma carga com falha. Se uma carga de assembly for bem-sucedida, seja porque foi carregada por outro assembly ou pelo host, ou porque estava presente no GAC, um manipulador de AssemblyResolve não será chamado.

Gerar redirecionamentos de ligação para projetos de testes unitários

Os projetos de teste unitário são compilados para DLLs, em vez de executáveis. A geração automática de redirecionamentos de vinculação aplica-se apenas aos tipos de saída executáveis, portanto, os projetos de testes unitários não recebem redirecionamentos por padrão. Quando um projeto de teste unitário faz referência a assemblies com versões conflitantes, os testes podem falhar em tempo de execução com exceções como FileLoadException.

Para gerar um .dll.config com redirecionamentos de associação para um projeto de teste unitário, adicione tanto o AutoGenerateBindingRedirects quanto o GenerateBindingRedirectsOutputType ao ficheiro do projeto.

<PropertyGroup>
  <AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
  <GenerateBindingRedirectsOutputType>true</GenerateBindingRedirectsOutputType>
</PropertyGroup>

A GenerateBindingRedirectsOutputType propriedade instrui o MSBuild a gerar um ficheiro .dll.config juntamente com a saída do conjunto de teste, mesmo que o tipo de saída seja uma biblioteca de classes (DLL). A maioria dos executores de testes, incluindo o VSTest, carrega este ficheiro de configuração durante a execução de testes.

Depois de adicionar estas propriedades e reconstruir o projeto, verifique se aparece um ficheiro de.dll.config no diretório de saída da build ao lado do conjunto de teste. O ficheiro contém os redirecionamentos de ligação necessários para resolver conflitos de versões de assembly durante a execução dos testes.

Redirecionar versões no nível da máquina

Pode haver casos raros em que um administrador de máquina deseja que todos os aplicativos em um computador usem uma versão específica de um assembly. Por exemplo, uma versão específica pode corrigir uma falha de segurança. Se um assembly for redirecionado no arquivo de configuração da máquina, chamado machine.config, todos os aplicativos nessa máquina que usam a versão antiga serão direcionados para usar a nova versão. O arquivo de configuração da máquina substitui o arquivo de configuração do aplicativo e o arquivo de política do editor. Este ficheiro machine.config está localizado em %windir%\Microsoft.NET\Framework[version]\config\machine.config para máquinas de 32 bits, ou %windir%\Microsoft.NET\Framework64[version]\config\machine.config para máquinas de 64 bits.

Especificar a vinculação de assembly em arquivos de configuração

Você usa o mesmo formato XML para especificar redirecionamentos de vinculação, seja no arquivo de configuração do aplicativo, no arquivo de configuração da máquina ou no arquivo de política do editor. Para redirecionar uma versão de assembly para outra, use o elemento <bindingRedirect>. O atributo oldVersion pode especificar uma única versão de assembly ou um intervalo de versões. O atributo newVersion deve especificar uma única versão. Por exemplo, <bindingRedirect oldVersion="1.1.0.0-1.2.0.0" newVersion="2.0.0.0"/> especifica que o runtime deve usar a versão 2.0.0.0 em vez das versões de montagem entre 1.1.0.0 e 1.2.0.0.

O exemplo de código a seguir demonstra vários cenários de redirecionamento de associações. O exemplo especifica um redirecionamento para um intervalo de versões para myAssemblye um único redirecionamento de vinculação para mySecondAssembly. O exemplo também especifica que o ficheiro de política do editor não substituirá os redirecionamentos de associação para myThirdAssembly.

Para vincular um assembly, deves especificar a cadeia de caracteres "urn:schemas-microsoft-com:asm.v1" com o atributo xmlns na tag <assemblyBinding>.

<configuration>
  <runtime>
    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
      <dependentAssembly>
        <assemblyIdentity name="myAssembly"
          publicKeyToken="32ab4ba45e0a69a1"
          culture="en-us" />
        <!-- Assembly versions can be redirected in app,
          publisher policy, or machine configuration files. -->
        <bindingRedirect oldVersion="1.0.0.0-2.0.0.0" newVersion="3.0.0.0" />
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="mySecondAssembly"
          publicKeyToken="32ab4ba45e0a69a1"
          culture="en-us" />
             <bindingRedirect oldVersion="1.0.0.0" newVersion="2.0.0.0" />
      </dependentAssembly>
      <dependentAssembly>
      <assemblyIdentity name="myThirdAssembly"
        publicKeyToken="32ab4ba45e0a69a1"
        culture="en-us" />
        <!-- Publisher policy can be set only in the app
          configuration file. -->
        <publisherPolicy apply="no" />
      </dependentAssembly>
    </assemblyBinding>
  </runtime>
</configuration>

Limitar associações de assembly a uma versão específica

Pode usar o atributo appliesTo no elemento <assemblyBinding> num ficheiro de configuração de aplicação para redirecionar referências de binding assembly para uma versão específica do .NET Framework. Este atributo opcional utiliza um número de versão do Framework .NET para indicar a que versão se aplica. Se não for especificado o atributo appliesTo, o elemento <assemblyBinding> aplica-se a todas as versões do .NET Framework.

Por exemplo, para redirecionar a associação de assemblagem para um assembly do .NET Framework 3.5, deverás incluir o seguinte código XML no ficheiro de configuração da tua aplicação.

<runtime>
  <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1"
    appliesTo="v3.5">
    <dependentAssembly>
      <!-- assembly information goes here -->
    </dependentAssembly>
  </assemblyBinding>
</runtime>

Você deve inserir as informações de redirecionamento na ordem de versão. Por exemplo, introduza a informação de redirecionamento de binding assembly para assemblies do .NET Framework 3.5, seguida das assemblies do .NET Framework 4.5. Finalmente, introduza a informação de redirecionamento assembly binding para qualquer redirecionamento assembly do .NET Framework que não utilize o atributo appliesTo e, portanto, se aplique a todas as versões do .NET Framework. Se houver um conflito no redirecionamento, a primeira instrução de redirecionamento correspondente no arquivo de configuração será usada.

Por exemplo, para redirecionar uma referência para um assembly do .NET Framework 3.5 e outra referência para um assembly do .NET Framework 4, use o padrão mostrado no seguinte pseudocódigo.

<assemblyBinding xmlns="..." appliesTo="v3.5 ">
  <!--.NET Framework version 3.5 redirects here -->
</assemblyBinding>

<assemblyBinding xmlns="..." appliesTo="v4.0.30319">
  <!--.NET Framework version 4.0 redirects here -->
</assemblyBinding>

<assemblyBinding xmlns="...">
  <!-- redirects meant for all versions of the runtime -->
</assemblyBinding>

Ver também