Nuget package explorer что это

Обновлено: 07.07.2024

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

Пакет NuGet – это всего лишь zip-файл, содержащий манифест и файлы, которые должны быть установлены в проекте Visual Studio. В него также должны входить три PowerShell скрипта, используемые для того, чтобы добавить автоматизацию во время инсталляции, удаления и запуска проекта. Пакет NuGet идентифицируется по его ID, который представляет собой строку, используемую для однозначной идентификации пакета и номера его версии. Файл манифеста содержит информацию о том, какие файлы должны быть добавлены в проект во время инсталляции, список зависимых пакетов и дополнительные метаданные, включая автора, URL веб-сайта проекта и лицензию URL.

NuGet предоставляет инструмент командной строки для создания пакетов и GUI-инструмент для просмотра существующих пакетов. Для того чтобы создать пакет, вам необходимо создать файл спецификации, который является XML-файлом. Этот файл используется в качестве входных данных для инструмента командной строки. Далее мы рассмотрим простую область, а затем упакуем ее.

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

Рисунок 19-1: Проект выделенной области библиотеки классов


Листинг 19-1: Наследование от PortableAreaRegistration

В этом листинге мы регистрируем нашу выделенную область. Это похоже на регулярные AreaRegistration классы, о которых мы писали в главе 13.

Следующим шагом является упаковка ее в NuGet пакет. Для этого мы введем несколько команд в окно NuGet Package Manager Console. Команды продемонстрированы в следующем листинге.

Листинг 19-3: Файл Nuspec для организации пакетов простой области

После создания пакета вы можете просмотреть содержимое пакета с помощью NuGet Package Explorer (рисунок 19-2). Вы увидите, что в состав выделенной области входят файлы представлений.

Рисунок 19-2: Просмотр содержимого пакета с помощью NuGet Package Explorer


В следующем разделе мы будем использовать выделенную область в нашем текущем приложении.

Применение выделенных областей

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

Сначала вам необходимо установить в вашем проекте пакет Portable Area с помощью следующей команды.

Листинг 19-4: Установка выделенной области

Для того чтобы в вашем приложении можно было использовать нашу новую область, вам необходимо вызвать API RegisterAllAreas в Global.asax.cs, как это продемонстрировано ниже.

При вызове AreaRegistration.RegisterAllAreas будет выполняться поиск любых комплектов в папке bin – если используемое вами приложение ссылается на ваш проект выделенной области, то поиск автоматически перемещается туда. Если наше приложение не ссылается на комплект выделенной области, то нам необходимо поместить его в папку bin. Это может быть сделано автоматически при помощи postbuild step, настраиваемого в закладке Build диалогового окна свойств проекта.

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

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

В статье показано как установить NuGet и что это такое. Показаны примеры управления пакетами NuGet. Достаточно подробно и с картинками.

Если не установлен NuGet

Что такое NuGet не буду подробно рассказывать, разве что пару строк:

Со страниц официального сайта

“NuGet is a Visual Studio extension that makes it easy to install and update open source libraries and tools in Visual Studio.”

А теперь на русском

“Nuget – это одно из расширение Visual Studio, которое позволяет с легкостью устанавливать, обновлять и удалять библиотеки (сборки), компоненты, инструменты.”

Если у Вас не установлен это замечательное расширения для Visual Studio, давайте установим. Запускаем студию, идем в меню: Tools –> Extention Manager. Откроется окно менеджера, в этом окне в левой части выберим Online Gallery, менеджер покажет список доспуных расширений. По идеи, Вы должны сразу увидеть Nuget Package Manager. Но если Вы не увидели его, напишите в строке поиска этого менеджера слово “nuget” и тогда точно перед Вами будет менеджер.

extention_manager

У меня на картинке NuGet Manager отмечен зеленой галкой, которая говорит, что расширение уже установлено. Если Вы нажмете кнопку Install, у Вас появится такой же зеленый значок.

Как установить пакет (способ 1 “Визуальный”)

Я создал просто консольное приложение (просто для демонстрации). В Solution Explorer правой кнопкой мыши нажимаем на Preferences и в меню выбираем пункт Add Library Package references. Этот пункт меню должен появиться после установки менеджера пакетов NuGet.

image

В открывшемся окне, также как и в менеджере расширений для Visual Studio, есть список доступных галерей (слева). Хочу напомнить, что можно получать пакеты как с официального сайта (NuGet official package source), так и папки на своем компьютере, так и с NuGet-сервера локальной сети.

Я в поиске написал свой ник и увидел список доступных пакетов, которые я сделал сам:

image

Допустим, что я хочу в своё консольное приложение добавить несколько классов и наполнить их данными, чтобы поэкспериментировать с LINQ. Я выберу пакет SampleData и нажму Install. После установки пакет отметился зеленой галкой, а в списке сборок проекта появилась сборка SampleData, которая содержит классы и данные для них:

Если запустить приложение, то я увижу

Как установить NuGet-пакет (способ 2 “Для продвинутых”)

Давайте теперь создадим другое приложение, пусть оно тоже будет консольное. Теперь будем устанавливать Implementation a simple IoC, этот пакет я сделал тоже сам и для себя (но можете тоже пользовать на здоровье). После установки Nuget Package Manager в меню Visual Studio появились новые пункты, например, Tools –> Library Package Manager –> Package Manager Console.

image

Открыв консоль можно писать команды для менеджера:

image

Обратите внимание, что выпадающее окно Package source позволяет выбрать конкретный источник пакетов или использовать все доступные.

Напишу-ка я команду для установки моего пакета с IoC:

Команда NuGetInstall-Package SimpleIoC

Пакет установлен. У меня в приложении появился файл SimpleIoC.cs, который является реализацией паттерна IoC (Инверсия в управлении). Кстати, в приложении появился еще одни новый файл packages.config, который, как раз, и содержит информацию об установленных пакетах. У меня в приложении он имеет теперь вид:

Ясно всё и понятно, что отображает этот файл.

Использование пакетов

Хочу отметить некоторую специфику в работе с пакетами. Дело в том, что пакеты это нечто иное, как просто файлы подгруженные к Вашему проекту с учетом некоторых параметров. Например, мой файл SimpleIoC.cs появляется в проекте с учетов namespace. Процесс подмены шаблона используется тот же, что использует Visual Studio, при создании нового проекта из шаблона (или файла из шаблона). Про свойства в таких шаблонах можно почитать хранилище знаний.

NuGet “умеет” добавлять и удалять сборки, файлы, папки, но при одном условии. Если папка, файл или сборка не поменяла название (содержание). Раз уж я установил пакет, то я могу его и удалить:

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

Технически NuGet Manager представляет собой расширение для Visual Studio, доступное программисту в процессе работы над своим проектом. Если вы используете «студию» версии 2012 и выше, то NuGet уже заранее предустановлен и готов к работе. В случае версии 2010 его нужно установить вручную. Его можно скачать либо с официального сайта, либо установить напрямую из Visual Studio через менеджер дополнений.

Давайте откроем менеджер. Для этого в Solution Explorer щелкаем правой кнопкой мыши по рабочему проекту и в контекстном меню выбираем пункт «Manage NuGet Packages…»:


NuGet Manager открывается в новой вкладке в текстовом редакторе. Интерфейс у него довольно простой.

Три главные вкладки:

  1. Browse. Найти и установить нужные нам пакеты из хранилища NuGet
  2. Installed. Список уже установленных в нашем проекте библиотек
  3. Updates. Библиотеки в нашем проекте, которые можно обновить до новой версии

Также в интерфейсе менеджера представлены:

  1. Строка поиска. Мы можем искать нужную нам библиотеку, начав вводить ее название
  2. Кнопка «Обновить состояние окна»
  3. Галочка «Включать в выдачу предрелизные версии библиотек», например, какие-то тестовые или экспериментальные
  4. Выпадающий список Package source. В каком месте менеджер будет искать нужные нам библиотеки
  5. Кнопка «Настройки менеджера»
  6. Главная панель с результатами выдачи (слева)
  7. Панель с описанием того компонента, который мы выбрали (справа)


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


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


Теперь давайте более детально посмотрим, что конкретно сделал менеджер при установке этого компонента в наш проект:
1. Он определил, что для данного пакета нет никаких сторонних зависимостей. Если бы они были, то менеджер автоматически их определил и подтянул.
2. NuGet Manager добавил ссылку на установленный компонент в наш проект (References):


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


4. В конфигурационный файл packages.config была добавлена запись о новом пакете:

5. В конфигурационный файл приложения web.config также были внесены необходимые изменения, чтобы подготовить компонент Entity Framework к работе:

Вот такие операции происходят, когда NuGet Manager добавляет новую библиотеку к нам в проект.

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

Давайте рассмотрим еще несколько моментов.

С NuGet Manager можно работать не только через графический интерфейс, но и через командную строку (консоль). Чтобы ее открыть, идем Tools -> NuGet Package Manager -> Package Manager Console.


Работа в консоли ничем не отличается от работы в графическом интерфейсе, это дело вкуса.

Управление осуществляется посредством специальных команд. Чтобы вывести в консоль список всех доступных команд нужно написать инструкцию:

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

Добавляем пакет Entity Framework в текущий проект:

Обновляем ранее установленный пакет:

Переустанавливаем ВСЕ пакеты во всех проектах в данном решении:

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

В видео версии этого урока более подробно и наглядно показана работа с этим инструментом.

Во время установки пакета, NuGet копирует файлы в проект и автоматически делает необходимые изменения, такие как добавление ссылок и изменение файлов конфигурации app.config или web.config. Если вы решили удалить библиотеку, NuGet удаляет установленные файлы, а также отменяет изменения сделанные при установке, таким образом не остается никакого мусора и беспорядка.

Пакеты NuGet

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

Использование NuGet в Visual Studio

NuGet работает во всех версиях Visual Studio 2012, Visual Studio 2010, Visual Web Developer 2010 и Windows Phone Developer Tools 7.1. Найти, установить, удалить или обновить пакеты можно в диалоговом окне Manage Nuget Packages или через командную строку PowerShell в Package Manager Console. Все это встроено в Visual Studio и доступно через главное меню и либо через контекстное меню в Solution Explorer.

Диалог управления пакетами NuGet

На картинке показан диалог управления пакетами NuGet. Вкладка Online показывает все доступные пакеты на официальном фиде.


Командная консоль управления пакетами

Так выглядит Командная консоль управления пакетами.


Поддерживаемые операционные системы

Для PowerShell командлетов (cmdlets) требуется PowerShell 2.0. Поэтому NuGet будет работать на следующих операционных системах:

Разумеется, нет смысла заниматься сразу реализацией реального API, проще проверить всё на маленьком примере. Именно так я и поступил, и хочу пройти путь до работающего решения ещё раз вместе с вами. Краткий список шагов будет приведён в конце статьи.

Первые попытки

Чтобы двинуться дальше, создадим проект нашей тестовой библиотеки. В файле .csproj DryWetMIDI указаны TFM netstandard2.0 и net45, поэтому для тестового проекта я также указал эти целевые платформы для приближения к реальным условиям. Проект назовём DualLibClassLibrary, внутри будет всего один файл Class.cs:

Кроме того, нам, разумеется, нужны сами нативные сборки (test.dll и test.dylib). Я собрал их из простого кода на C (к слову, такого подхода буду придерживаться затем и в реальной библиотеке):

Если интересно, файлы test.dll и test.dylib создавал в рамках тестового пайплайна в Azure DevOps (в действительности двух, для Windows и macOS). В конце концов, мне нужно будет делать всё в рамках CI, так что решил сразу проверить, как всё будет происходить в реальности. Пайплайн простой, состоит из 3 шагов:

1. сгенерировать файл с кодом на C (задача PowerShell):

( return 456; для macOS);

2. собрать библиотеку (задача Command Line):

(test.dylib для macOS);

3. опубликовать артефакт с библиотекой (задача Publish Pipeline Artifacts).

Итак, имеем файлы test.dll и test.dylib, предоставляющие одну и ту же функцию Foo , которая для Windows возвращает 123 , а для macOS – 456 , так что мы всегда сможем проверить корректность вызова и результата. Файлы положим рядом с DualLibClassLibrary.csproj.

Теперь нужно понять, как добавить их в NuGet пакет так, чтобы после установки пакета они копировались в выходную директорию при сборке приложения, обеспечивая таким образом работу установленной библиотеки. Так как библиотека у нас кроссплатформенная и использует новый формат файла .csproj (SDK style), очень хочется там и объявить инструкции для упаковки файлов. Изучив немного вопрос, пришёл к такому содержимому .csproj:

dotnet pack .\DualLibClassLibrary.sln -c Release

Файлы test.dll и test.dylib добавились из пакета

Выглядит обнадёживающе, пишем в файле Program.cs простой код:

Запускаем и грустим:

Программа не нашла файл test.dll

Программа не нашла файл test.dll

Что ж, заглянем в папку bin/Debug:

Файлы test.dll и test.dylib отсутствуют в выходной директории приложения

И правда нет файлов. Как же так, <CopyToOutputDirectory> мы им указали, в структуре проекта файлы видны. Проверив содержимое .csproj нашего приложения, всё становится понятно:

В csproj полный беспорядок с добавленными файлами

В csproj полный беспорядок с добавленными файлами

Во-первых, элемент <CopyToOutputDirectory> отсутствует, а во-вторых, по неведомой причине test.dylib добавился как элемент <None> , а test.dll как элемент <Content> . Остаётся только посмотреть содержимое файла .nupkg. Воспользовавшись программой NuGet Package Explorer, видим следующий манифест:

Как видим, файлы добавились без атрибута copyToOutput , что печально (про атрибут можно почитать в таблице тут: Using the contentFiles element for content files).

Копирование файлов в выходную директорию при сборке приложения

Элемент <PackageCopyToOutput> как раз должен привнести атрибут copyToOutput в манифест пакета. Кроме того, явно указал папки, куда нужно положить файлы, дабы избежать директорий вроде any. Подробнее о том, как всё это работает, можно почитать тут: Including content in a package.

Собираем снова наш пакет и проверяем манифест:

Теперь всё выглядит куда лучше, простая структура файлов и атрибут copyToOutput на месте. Устанавливаем библиотеку в наше консольное приложение и запускаем:

copyToOutput ситуацию не спасает

copyToOutput ситуацию не спасает

Всё так же файлов нет в выходной директории приложения

Всё так же файлов нет в выходной директории приложения

Кроме слегка изменённого текста исключения разницы не видно. Отписался в issue по итогу, на что мне ответили:

Please see our docs on contentFiles . It supports adding different content depending on project's target framework and language, and therefore needs files in a specific structure which your package is not currently using.

Есть статья в документации Microsoft с подозрительно нужным заголовком: Creating native packages. Статья не сильно содержательная, однако кое-что полезное из неё можно почерпнуть. А именно, что можно сделать файл .targets, где мы и укажем <CopyToOutputDirectory> нашим файлам. Сам файл .targets мы включим в пакет вместе с нативными библиотеками. Сказано – сделано. Создаём файл DualLibClassLibrary.targets:

А в файле DualLibClassLibrary.csproj пропишем:

Ошибка уже другая

Ошибка уже другая

Данная ошибка может возникнуть из-за несоответствующей разрядности приложения и нативных сборок. Я собирал их на 64-битных системах, приложение запускаю также в 64-битной ОС. Что ж, продолжаем наше путешествие.

Поддержка 32- и 64-битных процессов

Если зайти в свойства проекта приложения в Visual Studio на вкладку Build, обнаружим такую опцию:

Процесс будет 32-битным

Процесс будет 32-битным

Можно, конечно, выключить эту опцию, и приложение наконец напечатает верный результат:

Result = 123000. Press any key to exit.

Но, разумеется, это не решение по следующим причинам:

не будет возможности использовать библиотеку в 32-битных процессах;

придётся требовать от пользователей лишних действий в виде отключения галки;

Конечно же, так никуда не годится, и проблему нужно победить. На самом деле, вариант тут очевиден: сделать нативные сборки для каждой операционной системы в двух вариантах – 32- и 64-битном. То есть поставка пакета чуть распухнет, вместо 2 платформозависимых библиотек внутри будут 4. Я в этом ничего плохого не вижу, ибо файлы всё равно небольшие, а потому буду продолжать именно с этим подходом (тем более, что иного не придумал).

Немного расскажу о том, как собирал 32-битные версии библиотек. Как я упоминал выше, я произвожу сборку в конвейерах Azure DevOps через gcc. У gcc есть флаг -m32 , который, по идее, должен как раз собрать 32-битную библиотеку. На сборочных агентах с macOS всё здорово, а вот на Windows получил нелицеприятные логи:

C:/ProgramData/Chocolatey/lib/mingw/tools/install/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/8.1.0/../../../../x86_64-w64-mingw32/bin/ld.exe: skipping incompatible C:/ProgramData/Chocolatey/lib/mingw/tools/install/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/8.1.0/../../../../x86_64-w64-mingw32/lib\libuser32.a when searching for -luser32

C:/ProgramData/Chocolatey/lib/mingw/tools/install/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/8.1.0/../../../../x86_64-w64-mingw32/lib/libmsvcrt.a when searching for -lmsvcrt

C:/ProgramData/Chocolatey/lib/mingw/tools/install/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/8.1.0/../../../../x86_64-w64-mingw32/bin/ld.exe: cannot find -lmsvcrt

collect2.exe: error: ld returned 1 exit status

Задав вопрос и на StackOverflow, и в Microsoft Developer Community, выяснилось, что на агентах Microsoft не предустановлен 32-битный MinGW, что и приводит к падению. Попробовав множество вариантов, я остановился на проекте brechtsanders/winlibs_mingw, придя к простому PowerShell скрипту:

Используя поставляемый в составе архива компилятор i686-w64-mingw32-gcc.exe, удалось наконец-таки собрать 32-битный файл test.dll. Ура!

Теперь осталось придумать, как заставить нашу библиотеку вызывать API либо из 32- либо из 64-битной сборки. Я думаю, варианты тут есть разные, я остановился на таком:

собираем нативные библиотеки test32.dll, test64.dll, test32.dylib и test64.dylib;

делаем абстрактный класс Api с абстрактными методами, соответствующими нашему managed API для внутреннего использования;

делаем два наследника Api32 и Api64 , в которых реализуем абстрактный API из родительского класса, вызывая unmanaged API из test32 и test64 соответственно;

делаем класс ApiProvider , чьё свойство Api будет отдавать нам реализацию, соответствующую разрядности текущего процесса.

Приведу код файлов:

Api.cs

Api32.cs

Api64.cs

ApiProvider.cs

И тогда код нашего класса Class будет таким:

Собрав пакет (разумеется, обновив предварительно содержимое файлов DualLibClassLibrary.targets и DualLibClassLibrary.csproj, добавив новые файлы), убедимся, что метод нашей библиотеки работает корректно при любой разрядности процесса приложения.

Заключение

Я привёл полную хронологию моих мытарств касаемо создания NuGet пакета с платформозависимым API, но будет полезно кратко перечислить основные моменты (я же обещал инструкцию):

создать нативные сборки, причём в двух вариантах: 32- и 64-битном;

положить их рядом с проектом библиотеки (можно и в папку какую-то, главное путь указать к ним потом верный);

добавить файл .targets, в котором для всех нативных сборок добавить элемент <CopyToOutputDirectory> с желаемым значением;

в файле .csproj библиотеки прописать упаковку как нативных сборок, так и файла .targets (должен пойти в папку build пакета);

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

Это всё. Солюшн нашей тестовой библиотеки можно взять отсюда: DualLibClassLibrary.zip. Решение было проверено в следующих сценариях на Windows и macOS:

Касаемо проверки в 32- и 64-битном процессах – проверял только на Windows, не уверен, как проверить это на macOS.

Читайте также: