Поддержка нескольких версий .NET

Многие библиотеки предназначаются для определенной версии платформы .NET Framework. Например, у вас может быть одна версия библиотеки для универсальной платформы Windows и другая версия, использующая возможности .NET Framework 4.6. Для этого NuGet поддерживает включение нескольких версий одной и той же библиотеки в один пакет.

В этой статье описывается структура пакета NuGet независимо от того, как созданы пакет или сборки (то есть, когда компоновка одинакова при использовании нескольких файлов .csproj не на основе пакетов SDK и пользовательского файла .nuspec или одного файла .csproj на основе пакетов SDK с многоплатформенным нацеливанием). Для проекта в стиле пакета SDK целевой объект pack NuGet распознает, как должен располагаться пакет, и автоматизирует помещение сборок в правильные папки библиотеки и создание групп зависимостей для каждой целевой платформы (TFM). См. подробнее о включении поддержки выбора нескольких версий платформ .NET в файле проекта.

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

Структура папок, соответствующих версиям платформы

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

lib\{framework name}[{version}]

Полный список поддерживаемых имен см. в справочнике по целевым платформам.

Никогда не следует включать версию библиотеки, не относящуюся к конкретной платформе, помещая ее непосредственно в корневую папку lib. (Такая возможность поддерживалась только в packages.config.) В таком случае библиотека будет совместима с любой целевой платформой и ее можно будет установить где угодно, что, скорее всего, приведет к непредвиденным ошибкам во время выполнения. Возможность добавления сборок в корневую папку (например, lib\abc.dll) или ее вложенные папки (например, lib\abc\abc.dll) является нерекомендуемой и игнорируется при использовании формата PackagesReference.

Например, следующая структура папок поддерживает четыре версии сборки для конкретных платформ:

\lib
    \net46
        \MyAssembly.dll
    \net461
        \MyAssembly.dll
    \uap
        \MyAssembly.dll
    \netcore
        \MyAssembly.dll

Чтобы легко включить все эти файлы при сборке пакета, используйте рекурсивный подстановочный знак ** в разделе <files> файла .nuspec:

<files>
    <file src="lib\**" target="lib/{framework name}[{version}]" />
</files>

Папки для конкретных архитектур

Если имеются сборки для конкретных архитектур, то есть отдельные сборки для архитектур ARM, x86 и x64, их необходимо поместить в папку с именем runtimes во вложенные папки {platform}-{architecture}\lib\{framework} или {platform}-{architecture}\native. Например, следующая структура папок содержит как библиотеки DLL в машинном коде, так и управляемые библиотеки DLL для Windows 10 и платформы uap10.0:

\runtimes
    \win10-arm
        \native
        \lib\uap10.0
    \win10-x86
        \native
        \lib\uap10.0
    \win10-x64
        \native
        \lib\uap10.0

Эти сборки будут доступны только во время выполнения. Поэтому если вы хотите предоставить соответствующую сборку, используемую во время компиляции, добавьте сборку AnyCPU в папку /ref/{tfm}.

Обратите внимание, что NuGet всегда извлекает ресурсы, используемые во время компиляции или выполнения, из одной папки. Если в папке /ref есть совместимые ресурсы, то из папки /lib не будут добавляться сборки, используемые во время компиляции. Соответственно, если в папке /runtimes есть совместимые ресурсы, то ресурсы из папки /lib будут игнорироваться.

Пример указания ссылок на эти файлы в манифесте .nuspec см. в разделе Создание пакетов универсальной платформы Windows.

Также ознакомьтесь с записью блога об упаковке компонента приложения для Магазина Windows с помощью NuGet.

Сопоставление версий сборки и целевых платформ в проекте

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

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

Например, рассмотрим следующую структуру папок в пакете:

\lib
    \net45
        \MyAssembly.dll
    \net461
        \MyAssembly.dll

При установке этого пакета в проекте, предназначенном для .NET Framework 4.6, NuGet устанавливает сборку из папки net45, так как это самая старшая доступная версия не выше 4.6.

Если же проект предназначен для .NET Framework 4.6.1, NuGet устанавливает сборку в папке net461.

Если проект предназначен для .NET Framework 4.0 или более ранней версии, NuGet выдает сообщение об ошибке отсутствия совместимой сборки.

Группирование сборок по версии платформы

NuGet копирует сборки только из одной папки библиотеки в проекте. Предположим, есть пакет со следующей структурой папок:

\lib
    \net40
        \MyAssembly.dll (v1.0)
        \MyAssembly.Core.dll (v1.0)
    \net45
        \MyAssembly.dll (v2.0)

Когда этот пакет устанавливается в проекте, предназначенном для .NET Framework 4.5, устанавливается только сборка MyAssembly.dll (версия 2.0). Сборка MyAssembly.Core.dll (версия 1.0) не устанавливается, так как ее нет в папке net45. Такое поведение NuGet обусловлено тем, что сборка MyAssembly.Core.dll могла быть объединена с версией 2.0 сборки MyAssembly.dll.

Чтобы установить сборку MyAssembly.Core.dll для .NET Framework 4.5, поместите ее копию в папку net45.

Группирование сборок по профилю платформы

NuGet также поддерживает нацеливание на определенный профиль платформы путем добавления дефиса и имени платформы в конце имени папки.

lib{framework name}-{profile}

Поддерживаются следующие профили:

  • client: клиентский профиль;
  • full: полный профиль;
  • wp: Windows Phone;
  • cf: Compact Framework.

Объявление зависимостей (расширенные сценарии)

При упаковке файла проекта NuGet пытается автоматически создать зависимости из проекта. Приведенные в этом разделе инструкции по объявлению зависимостей с помощью файла .nuspec обычно выполняются только в расширенных сценариях.

(Версия 2.0+) Зависимости пакетов можно объявить в файле .nuspec с учетом целевой платформы целевого проекта с помощью элементов <group> в элементе <dependencies>. См. об элементах зависимостей.

Каждый элемент group имеет атрибут targetFramework и содержит ноль или более элементов <dependency>. Эти зависимости устанавливаются вместе, если целевая платформа совместима с профилем платформы проекта. Точное описание идентификаторов платформы см. в разделе Целевые платформы.

Мы рекомендуем использовать одну группу для моникера целевой платформы (TFM) для файлов в папках lib/ и ref/.

В следующем примере приводятся различные варианты элемента <group>:

<dependencies>

    <group targetFramework="net472">
        <dependency id="jQuery" version="1.10.2" />
        <dependency id="WebActivatorEx" version="2.2.0" />
    </group>

    <group targetFramework="net20">
    </group>

</dependencies>

Определение требуемой цели NuGet

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

Файлы содержимого и скрипты PowerShell

Предупреждение

Изменяемые файлы содержимого и выполнение скриптов можно использовать только с форматом packages.config. Их не рекомендуется использовать с другими форматами и не следует применять для новых пакетов.

При использовании packages.config файлы содержимого и скрипты PowerShell можно группировать по целевой платформе в папках content и tools, используя те же соглашения в отношении папок. Например:

\content
    \net46
        \MyContent.txt
    \net461
        \MyContent461.txt
    \uap
        \MyUWPContent.html
    \netcore
\tools
    init.ps1
    \net46
        install.ps1
        uninstall.ps1
    \uap
        install.ps1
        uninstall.ps1

Если папка платформы пуста, NuGet не добавляет ссылки на сборки или файлы содержимого и не выполняет скрипты PowerShell для этой платформы.

Примечание.

Так как скрипт init.ps1 выполняется на уровне решения независимо от проекта, его необходимо поместить непосредственно в папку tools. Если он находится в папке платформы, то он игнорируется.