Перенаправление версий сборок

Заметка

Эта статья связана с .NET Framework. Он не применяется к более новым реализациям .NET, включая .NET 6 и более поздних версий.

Вы можете перенаправить ссылки на привязку во время компиляции к сборкам .NET Framework, сторонним сборкам или сборкам собственного приложения. Вы можете перенаправить приложение для использования другой версии сборки несколькими способами: с помощью политики издателя, файла конфигурации приложения или файла конфигурации компьютера. В этой статье описывается, как привязка сборок работает в .NET Framework и как ее можно настроить.

Совет

Эта статья связана с приложениями .NET Framework. Сведения о загрузке сборок в .NET 5+ (и .NET Core) см. в разделе Dependency loading in .NET.

Унификация сборок и привязка по умолчанию

Привязки к сборкам платформы .NET иногда перенаправляются через процесс, называемый assembly объединение. .NET Framework состоит из версии среды CLR и около двух десятков сборок .NET Framework, составляющих библиотеку типов. Эти сборки .NET Framework обрабатываются средой выполнения как единая единица. По умолчанию при запуске приложения все ссылки на типы в коде, выполняемые средой выполнения, направляются в сборки .NET Framework с тем же номером версии, что и среда выполнения, загруженная в процессе. Перенаправления, происходящие с этой моделью, являются поведением по умолчанию для среды выполнения.

Например, если приложение ссылается на типы в пространстве имен System.XML и было создано с помощью платформы .NET Framework 4.5, она содержит статические ссылки на сборку System.XML, которая поставляется с средой выполнения версии 4.5. Если вы хотите перенаправить ссылку на привязку, чтобы указать на сборку System.XML, которая поставляется с .NET Framework 4, можно поместить сведения о перенаправлении в файл конфигурации приложения. Перенаправление привязки в файле конфигурации для единой сборки .NET Framework отменяет объединение для этой сборки.

Кроме того, вы можете захотеть вручную выполнить перенаправление биндировки для сторонних сборок, если доступно несколько версий.

Совет

Если вы обновляете пакет NuGet, на который ваше приложение ссылается косвенно, и начинаете замечать новые ошибки, такие как FileLoadException, MissingMethodException, TypeLoadExceptionили FileNotFoundException, может потребоваться включить автоматическое перенаправление привязок или вручную добавить перенаправление привязки. Это нормально при обновлении пакетов NuGet и является результатом создания некоторых пакетов для более старой версии зависимости. Следующий фрагмент файла конфигурации приложения добавляет перенаправление привязки для пакета 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>

Перенаправление версий с помощью политики издателя

Поставщики сборок могут направлять приложения в более новую версию сборки, включив файл политики издателя с новой сборкой. Файл политики издателя, расположенный в глобальном кэше сборок, содержит параметры перенаправления сборок.

Каждый основных.дополнительный версии сборки имеет собственный файл политики издателя. Например, перенаправления с версии 2.0.2.222 на 2.0.3.000 и с версии 2.0.2.321 до версии 2.0.3.000 оба переходят в один файл, так как они связаны с версией 2.0. Однако перенаправление с версии 3.0.0.999 на версию 4.0.0.000 перенаправляется в файл для версии 3.0.0.999. Каждая основная версия платформы .NET Framework имеет собственный файл политики издателя.

Если файл политики издателя существует для сборки, среда выполнения проверяет этот файл после проверки файла манифеста сборки и файла конфигурации приложения. Поставщики должны использовать файлы политики издателя, только если новая сборка обратно совместима с перенаправленной сборкой.

Политику издателя можно обойти, указав параметры в файле конфигурации приложения, как описано в разделе Обход политики издателя.

Перенаправление версий на уровне приложения

Существует несколько различных методов изменения поведения привязки для вашего приложения с помощью файла конфигурации приложения: вы можете вручную изменить файл, использовать автоматическое перенаправление привязки, или можно указать поведение привязки, посредством обхода политики издателя.

Изменение файла конфигурации приложения вручную

Вы можете вручную изменить файл конфигурации приложения, чтобы устранить проблемы сборки. Например, если поставщик выпускает более новую версию сборки, которую приложение использует без предоставления политики издателя (так как они не гарантируют обратную совместимость), вы можете направить приложение на использование более новой версии сборки, поместив сведения о привязке сборки в файл конфигурации приложения следующим образом.

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

Полагайтесь на автоматическое перенаправление привязки

При создании классического приложения в Visual Studio, предназначенных для .NET Framework 4.5.1 или более поздней версии, приложение использует автоматическое перенаправление привязок. Это означает, что если два компонента ссылаются на разные версии одной и той же сборки с строгим именем, среда выполнения автоматически добавляет перенаправление привязки на более новую версию сборки в файл конфигурации выходного приложения (app.config). Это перенаправление отменяет унификацию сборок, которая могла бы произойти в противном случае. Исходный app.config файл не изменяется. Например, предположим, что приложение напрямую ссылается на компонент .NET Framework, но использует стороннюю библиотеку, предназначенную для более старой версии того же компонента. При компиляции приложения файл конфигурации выходного приложения изменяется, чтобы содержать перенаправление привязки к более новой версии компонента.

При создании веб-приложения вы получите предупреждение сборки о конфликте привязки, которое, в свою очередь, дает возможность добавить необходимое перенаправление привязки в исходный файл веб-конфигурации.

Если вы вручную добавляете перенаправления привязки в исходный файл app.config во время компиляции, Visual Studio пытается объединить сборки на основе добавленных перенаправлений привязки. Например, предположим, что вы вставляете следующее перенаправление привязки для сборки:

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

Если другой проект в приложении ссылается на версию 1.0.0.0 той же сборки, автоматическое перенаправление привязок добавляет следующую запись в выходной файл app.config, чтобы приложение было унифицировано в версии 2.0.0.0 этой сборки:

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

Вы можете включить автоматическое перенаправление привязок, если приложение предназначено для более старых версий .NET Framework. Это поведение по умолчанию можно переопределить, предоставив сведения о перенаправлении привязки в файле app.config для любой сборки или отключив функцию перенаправления привязки. Сведения о включении или отключении этой функции см. в разделе Практическое руководство. Включение и отключение автоматического перенаправления привязок.

Обход политики издателя

При необходимости можно переопределить политику издателя в файле конфигурации приложения. Например, новые версии сборок, которые заявляют о своей обратной совместимости, по-прежнему могут нарушить работу приложения. Если вы хотите обойти политику издателя, в файле конфигурации приложения добавьте элемент <publisherPolicy> в элемент зависимости <Assembly> и задайте для атрибута apply значение no, которое переопределяет все предыдущие параметры yes.

<publisherPolicy apply="no" />

Чтобы сохранить работу вашего приложения для пользователей, обходите политику издателя, но обязательно сообщайте о проблеме поставщику сборок. Если у сборки есть файл политики издателя, поставщик должен убедиться, что сборка является обратно совместимой, и клиенты могут использовать новую версию максимально возможно.

Перенаправление версий для тестов, подключаемых модулей или библиотек, используемых другим компонентом

Для тестов необходимо создать файл .dll.config. Большинство существующих платформ модульных тестов учитывают эти файлы при загрузке тестов.

Подключаемые модули могут учитывать файлы .dll.config, однако могут и не учитывать их. Единственным надежным механизмом для перенаправлений является предоставление bindingRedirects при создании AppDomain.

Вы можете попытаться решить эту проблему с обработчиками событий AssemblyResolve, но это не работает, так как эти обработчики вызываются только при неудачной загрузке. Если загрузка сборки завершается успешно, либо потому что она была загружена другой сборкой, либо хостом, или присутствует в GAC, то обработчик AssemblyResolve не будет вызываться.

Создание перенаправлений привязки для проектов модульного теста

Проекты модульного теста компилируются в библиотеки DLL, а не исполняемые файлы. Автоматическое создание перенаправления привязки применяется только к исполняемым типам выходных данных, поэтому проекты модульного теста по умолчанию не получают перенаправления привязки. Когда проект модульного теста ссылается на сборки, имеющие конфликтующие версии, тесты могут завершаться ошибкой во время выполнения с исключениями, такими как FileLoadException.

Чтобы создать файл .dll.config с перенаправлениями привязки для проекта модульного теста, добавьте и AutoGenerateBindingRedirectsGenerateBindingRedirectsOutputType в файл проекта:

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

Свойство GenerateBindingRedirectsOutputType указывает MSBuild создать файл.dll.config вместе с выходными данными тестовой сборки, даже если тип вывода является библиотекой классов (DLL). Большинство тестовых модулей, включая VSTest, загружают этот файл конфигурации при выполнении тестов.

После добавления этих свойств и перестроения проекта убедитесь, что файл .dll.config появится в выходном каталоге сборки рядом с тестовой сборкой. Файл содержит перенаправления привязки, необходимые для разрешения конфликтов версий сборки во время тестового выполнения.

Перенаправление версий на уровне компьютера

Иногда администратор компьютера хочет, чтобы все приложения на компьютере использовали определенную версию сборки. Например, определенная версия может исправить отверстие безопасности. Если сборка перенаправляется в файле конфигурации компьютера с именем machine.config, все приложения на этом компьютере, использующие старую версию, переключаются на новую версию. Файл конфигурации компьютера переопределяет файл конфигурации приложения и файл политики издателя. Этот файл machine.config находится в %windir%\Microsoft.NET\Framework[version]\config\machine.config для 32-разрядных компьютеров или %windir%\Microsoft.NET\Framework64[version]\config\machine.config для 64-разрядных компьютеров.

Укажите привязку сборки в файлах конфигурации

Вы используете тот же формат XML, чтобы указать перенаправления привязки, будь то в файле конфигурации приложения, файле конфигурации компьютера или файле политики издателя. Чтобы перенаправить одну версию сборки в другую, используйте элемент <bindingRedirect>. Атрибут oldVersion может указывать одну версию сборки или диапазон версий. Атрибут newVersion должен указывать одну версию. Например, <bindingRedirect oldVersion="1.1.0.0-1.2.0.0" newVersion="2.0.0.0"/> указывает, что среда выполнения должна использовать версию 2.0.0.0.0 вместо версий сборок от 1.1.0.0 до 1.2.0.0.0.

В следующем примере кода демонстрируется множество сценариев перенаправления привязки. В примере указывается перенаправление для диапазона версий для myAssemblyи одно перенаправление привязки для mySecondAssembly. В примере также указывается, что файл политики издателя не переопределяет перенаправления привязки для myThirdAssembly.

Чтобы привязать сборку, необходимо указать строку urn:schemas-microsoft-com:asm.v1 с атрибутом xmlns в теге <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>

Ограничение привязок сборок к определенной версии

Атрибут appliesTo можно использовать в элементе <assemblyBinding> в файле конфигурации приложения для перенаправления ссылок на привязку сборок в определенную версию .NET Framework. Этот необязательный атрибут использует номер версии .NET Framework, чтобы указать, к какой версии она применяется. Если атрибут appliesTo не указан, элемент <assemblyBinding> применяется ко всем версиям .NET Framework.

Например, чтобы перенаправить привязку сборки для сборки .NET Framework 3.5, в файл конфигурации приложения будет включен следующий XML-код.

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

Необходимо ввести сведения о перенаправлении в порядке версий. Например, введите сведения о перенаправлении привязки сборок для сборок .NET Framework 3.5, за которыми следует .NET сборки Framework 4.5. Наконец, введите сведения о перенаправлении привязки сборок для любого перенаправления сборок .NET Framework, который не использует атрибут appliesTo и поэтому применяется ко всем версиям .NET Framework. При возникновении конфликта при перенаправлении используется первая совпадающая инструкция перенаправления в файле конфигурации.

Например, чтобы перенаправить одну ссылку на сборку .NET Framework 3.5 и другую ссылку на сборку .NET Framework 4, используйте шаблон, показанный в следующем псевдокоде.

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

См. также