Создание пакетов для Xamarin с помощью Visual Studio 2017 или 2019

Пакет Xamarin содержит код, использующий собственные API в iOS, Android и Windows в зависимости от операционной системы во время выполнения. Хотя это несложно сделать, предпочтительнее позволить разработчикам использовать пакет из библиотек .NET Standard или PCL через общую контактную зону API.

В этом пошаговом руководстве с помощью Visual Studio 2017 или 2019 вы создадите кроссплатформенный пакет NuGet, который можно использовать в проектах для мобильных устройств в Windows, iOS и Android.

  1. Предварительные требования
  2. Создание структуры проекта и кода абстракции
  3. Написание кода для конкретных платформ
  4. Создание и изменение файла NUSPEC
  5. Упаковка компонента
  6. Связанные темы

Предварительные требования

  1. Visual Studio 2017 или 2019 с универсальной платформой Windows (UWP) и Xamarin. Установите бесплатный выпуск Community с сайта visualstudio.com. Вы также можете использовать выпуски Professional и Enterprise. Чтобы включить средства UWP и Xamarin, выберите "Выборочная установка" и задайте соответствующие параметры.
  2. Интерфейс командной строки NuGet. Скачайте последнюю версию nuget.exe на странице nuget.org/downloads, сохранив ее в любом месте на ваш выбор. Затем добавьте это расположение в переменную среды PATH, если это еще не сделано.

Примечание

nuget.exe является программой интерфейса командной строки, а не установщиком, поэтому сохраните скачиваемый из браузера файл, но не запускайте его.

Создание структуры проекта и кода абстракции

  1. Скачайте и запустите расширение шаблонов кроссплатформенного подключаемого модуля .NET Standard для Visual Studio. Эти шаблоны упрощают создание структуры проекта для этого пошагового руководства.

  2. В Visual Studio 2017, file > New > Project, search forPlugin, select the Cross-Platform .NET Standard Library Plugin template, change the name to LoggingLibrary, and click OK.

    New Blank App (Xamarin.Forms Portable) project in VS 2017

    В Visual Studio 2019 г. найдите > новый > Project, выберите шаблон подключаемого модуля стандартной библиотеки кроссплатформенного .NET и нажмите кнопку "Далее".Plugin

    New Blank App (Xamarin.Forms Portable) project in VS 2019

    Измените имя на LoggingLibrary и щелкните "Создать".

    New Blank App (Xamarin.Forms Portable) configuration in VS 2019

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

  • Проект ILoggingLibrary, который содержится в файле ILoggingLibrary.shared.cs, определяет общий интерфейс (контактную зону API) компонента. Именно здесь вы можете определить интерфейс для библиотеки.
  • Другой общий проект содержит код в CrossLoggingLibrary.shared.cs, который будет определять реализацию абстрактного интерфейса во время выполнения для конкретной платформы. В общем случае изменять этот файл не требуется.
  • Проекты, зависящие от платформы, например LoggingLibrary.android.cs, содержат собственную реализацию интерфейса в соответствующих LoggingLibraryImplementation.cs файлах (VS 2017) или LoggingLibrary.<PLATFORM>.cs (VS 2019). Именно здесь вы можете создать код библиотеки.

По умолчанию файл ILoggingLibrary.shared.cs проекта ILoggingLibrary содержит определение интерфейса, но не методы. В рамках этого пошагового руководства добавьте метод Log следующим образом:

using System;
using System.Collections.Generic;
using System.Text;

namespace Plugin.LoggingLibrary
{
    /// <summary>
    /// Interface for LoggingLibrary
    /// </summary>
    public interface ILoggingLibrary
    {
        /// <summary>
        /// Log a message
        /// </summary>
        void Log(string text);
    }
}

Написание кода для конкретных платформ

Чтобы реализовать интерфейс ILoggingLibrary и его методы для конкретной платформы, сделайте следующее:

  1. Откройте файл LoggingLibraryImplementation.cs (VS 2017) или LoggingLibrary.<PLATFORM>.cs (VS 2019) для проекта каждой платформы и добавьте необходимый код. Например (при использовании проекта платформы Android):

    using System;
    using System.Collections.Generic;
    using System.Text;
    
    namespace Plugin.LoggingLibrary
    {
        /// <summary>
        /// Implementation for Feature
        /// </summary>
        public class LoggingLibraryImplementation : ILoggingLibrary
        {
            /// <summary>
            /// Log a message
            /// </summary>
            public void Log(string text)
            {
                throw new NotImplementedException("Called Log on Android");
            }
        }
    }
    
  2. Повторите эту реализацию в проектах для каждой платформы, которую требуется поддерживать.

  3. Щелкните правой кнопкой мыши решение и выберите Собрать решение, чтобы проверить свою работу и создать артефакты, которые вы затем упакуете. Если возникают ошибки об отсутствующих ссылках, щелкните решение правой кнопкой мыши, выберите Восстановить пакеты NuGet, чтобы установить зависимости, и повторите сборку.

Примечание

Если вы используете Visual Studio 2019, перед тем как выбрать параметр Восстановить пакеты NuGet и попытаться выполнить перестроение, необходимо изменить версию MSBuild.Sdk.Extras на 2.0.54 в LoggingLibrary.csproj. Доступ к этому файлу можно получить только щелкнув правой кнопкой мыши проект (под решением) и выбрав Unload Project, после чего нужно щелкнуть правой кнопкой мыши выгруженный проект и выбрать Edit LoggingLibrary.csproj.

Примечание

Чтобы выполнить сборку для iOS, необходим сетевой Mac, подключенный к Visual Studio, как описано в разделе Введение в Xamarin.iOS для Visual Studio. Если у вас нет доступного Mac, очистите проект iOS в диспетчере конфигураций (шаг 3 выше).

Создание и изменение файла NUSPEC

  1. Откройте командную строку, перейдите в папку LoggingLibrary, находящуюся на один уровень ниже места расположения файла .sln, и выполните команду NuGet spec, чтобы создать первичный файл Package.nuspec:

    nuget spec
    
  2. Переименуйте этот файл на LoggingLibrary.nuspec и откройте его в редакторе.

  3. Измените содержимое файла так, как показано ниже, заменив YOUR_NAME на соответствующее значение. Значение <id> должно быть уникальным в пределах nuget.org (см. соглашения об именовании, описанные в разделе Создание пакета). Кроме того, обратите внимание на то, что необходимо изменить теги author и description, иначе на этапе упаковки произойдет ошибка.

    <?xml version="1.0"?>
    <package >
        <metadata>
        <id>LoggingLibrary.YOUR_NAME</id>
        <version>1.0.0</version>
        <title>LoggingLibrary</title>
        <authors>YOUR_NAME</authors>
        <owners>YOUR_NAME</owners>
        <requireLicenseAcceptance>false</requireLicenseAcceptance>
        <description>Awesome application logging utility</description>
        <releaseNotes>First release</releaseNotes>
        <copyright>Copyright 2018</copyright>
        <tags>logger logging logs</tags>
        </metadata>
    </package>
    

Совет

Вы можете добавить для версии пакета суффикс -alpha, -beta или -rc, чтобы пометить пакет как предварительную версию. Дополнительные сведения о предварительных версиях см. в разделе Предварительные версии.

Добавление базовых сборок

Чтобы включить базовые сборки для конкретной платформы, добавьте следующий код в элемент <files> файла LoggingLibrary.nuspec соответствующим образом для поддерживаемых платформ:

<!-- Insert below <metadata> element -->
<files>
    <!-- Cross-platform reference assemblies -->
    <file src="Plugin.LoggingLibrary\bin\Release\Plugin.LoggingLibrary.dll" target="lib\netstandard1.4\Plugin.LoggingLibrary.dll" />
    <file src="Plugin.LoggingLibrary\bin\Release\Plugin.LoggingLibrary.xml" target="lib\netstandard1.4\Plugin.LoggingLibrary.xml" />
    <file src="Plugin.LoggingLibrary.Abstractions\bin\Release\Plugin.LoggingLibrary.Abstractions.dll" target="lib\netstandard1.4\Plugin.LoggingLibrary.Abstractions.dll" />
    <file src="Plugin.LoggingLibrary.Abstractions\bin\Release\Plugin.LoggingLibrary.Abstractions.xml" target="lib\netstandard1.4\Plugin.LoggingLibrary.Abstractions.xml" />

    <!-- iOS reference assemblies -->
    <file src="Plugin.LoggingLibrary.iOS\bin\Release\Plugin.LoggingLibrary.dll" target="lib\Xamarin.iOS10\Plugin.LoggingLibrary.dll" />
    <file src="Plugin.LoggingLibrary.iOS\bin\Release\Plugin.LoggingLibrary.xml" target="lib\Xamarin.iOS10\Plugin.LoggingLibrary.xml" />

    <!-- Android reference assemblies -->
    <file src="Plugin.LoggingLibrary.Android\bin\Release\Plugin.LoggingLibrary.dll" target="lib\MonoAndroid10\Plugin.LoggingLibrary.dll" />
    <file src="Plugin.LoggingLibrary.Android\bin\Release\Plugin.LoggingLibrary.xml" target="lib\MonoAndroid10\Plugin.LoggingLibrary.xml" />

    <!-- UWP reference assemblies -->
    <file src="Plugin.LoggingLibrary.UWP\bin\Release\Plugin.LoggingLibrary.dll" target="lib\UAP10\Plugin.LoggingLibrary.dll" />
    <file src="Plugin.LoggingLibrary.UWP\bin\Release\Plugin.LoggingLibrary.xml" target="lib\UAP10\Plugin.LoggingLibrary.xml" />
</files>

Примечание

Чтобы сократить имена файлов DLL и XML, щелкните правой кнопкой мыши любой заданный проект, откройте вкладку Библиотека и измените имена сборок.

Добавление зависимостей

При наличии конкретных зависимостей для собственных реализаций укажите их с помощью элемента <dependencies> с элементами <group>, например:

<!-- Insert within the <metadata> element -->
<dependencies>
    <group targetFramework="MonoAndroid">
        <!--MonoAndroid dependencies go here-->
    </group>
    <group targetFramework="Xamarin.iOS10">
        <!--Xamarin.iOS10 dependencies go here-->
    </group>
    <group targetFramework="uap">
        <!--uap dependencies go here-->
    </group>
</dependencies>

Например, следующий код задает iTextSharp в качестве зависимости для целевого объекта UAP:

<dependencies>
    <group targetFramework="uap">
        <dependency id="iTextSharp" version="5.5.9" />
    </group>
</dependencies>

Итоговый файл NUSPEC

Итоговый файл .nuspec должен выглядеть следующим образом (YOUR_NAME, и в этом случае необходимо заменить на соответствующее значение):

<?xml version="1.0"?>
<package >
    <metadata>
    <id>LoggingLibrary.YOUR_NAME</id>
    <version>1.0.0</version>
    <title>LoggingLibrary</title>
    <authors>YOUR_NAME</authors>
    <owners>YOUR_NAME</owners>
    <requireLicenseAcceptance>false</requireLicenseAcceptance>
    <description>Awesome application logging utility</description>
    <releaseNotes>First release</releaseNotes>
    <copyright>Copyright 2018</copyright>
    <tags>logger logging logs</tags>
        <dependencies>
        <group targetFramework="MonoAndroid">
            <!--MonoAndroid dependencies go here-->
        </group>
        <group targetFramework="Xamarin.iOS10">
            <!--Xamarin.iOS10 dependencies go here-->
        </group>
        <group targetFramework="uap">
            <dependency id="iTextSharp" version="5.5.9" />
        </group>
    </dependencies>
    </metadata>
    <files>
        <!-- Cross-platform reference assemblies -->
        <file src="Plugin.LoggingLibrary\bin\Release\Plugin.LoggingLibrary.dll" target="lib\netstandard1.4\Plugin.LoggingLibrary.dll" />
        <file src="Plugin.LoggingLibrary\bin\Release\Plugin.LoggingLibrary.xml" target="lib\netstandard1.4\Plugin.LoggingLibrary.xml" />
        <file src="Plugin.LoggingLibrary.Abstractions\bin\Release\Plugin.LoggingLibrary.Abstractions.dll" target="lib\netstandard1.4\Plugin.LoggingLibrary.Abstractions.dll" />
        <file src="Plugin.LoggingLibrary.Abstractions\bin\Release\Plugin.LoggingLibrary.Abstractions.xml" target="lib\netstandard1.4\Plugin.LoggingLibrary.Abstractions.xml" />

        <!-- iOS reference assemblies -->
        <file src="Plugin.LoggingLibrary.iOS\bin\Release\Plugin.LoggingLibrary.dll" target="lib\Xamarin.iOS10\Plugin.LoggingLibrary.dll" />
        <file src="Plugin.LoggingLibrary.iOS\bin\Release\Plugin.LoggingLibrary.xml" target="lib\Xamarin.iOS10\Plugin.LoggingLibrary.xml" />

        <!-- Android reference assemblies -->
        <file src="Plugin.LoggingLibrary.Android\bin\Release\Plugin.LoggingLibrary.dll" target="lib\MonoAndroid10\Plugin.LoggingLibrary.dll" />
        <file src="Plugin.LoggingLibrary.Android\bin\Release\Plugin.LoggingLibrary.xml" target="lib\MonoAndroid10\Plugin.LoggingLibrary.xml" />

        <!-- UWP reference assemblies -->
        <file src="Plugin.LoggingLibrary.UWP\bin\Release\Plugin.LoggingLibrary.dll" target="lib\UAP10\Plugin.LoggingLibrary.dll" />
        <file src="Plugin.LoggingLibrary.UWP\bin\Release\Plugin.LoggingLibrary.xml" target="lib\UAP10\Plugin.LoggingLibrary.xml" />
    </files>
</package>

Упаковка компонента

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

nuget pack LoggingLibrary.nuspec

Это действие создаст файл LoggingLibrary.YOUR_NAME.1.0.0.nupkg. Если открыть файл в таком средстве, как обозреватель пакетов NuGet, и развернуть все узлы, отобразится следующее содержимое:

NuGet Package Explorer showing the LoggingLibrary package

Совет

Файл .nupkg — это просто ZIP-файл с другим расширением. Поэтому чтобы просмотреть содержимое пакета, можно просто изменить расширение .nupkg на .zip, но не забудьте восстановить расширение перед отправкой пакета на сайт nuget.org.

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