Переносимые библиотеки классов (PCL)

Совет

Переносимые библиотеки классов (PCLs) считаются устаревшими в последних версиях Visual Studio. Хотя вы по-прежнему можете открывать, изменять и компилировать PCLs, для новых проектов рекомендуется использовать библиотеки .NET Standard для доступа к большей области поверхности API.

Ключевым компонентом создания кроссплатформенных приложений является возможность совместного использования кода в различных проектах, относящихся к платформе. Однако это усложняется тем, что разные платформы часто используют другой под набор библиотеки базовых классов .NET (BCL), поэтому фактически создаются в другой профиль библиотеки .NET Core. Это означает, что каждая платформа может использовать только библиотеки классов, предназначенные для одного профиля, чтобы они, как представляется, требовали отдельных проектов библиотек классов для каждой платформы.

Существует три основных подхода к совместному использованию кода, которые решают эту проблему: проекты .NET Standard, проекты общего ресурса и переносимая библиотека классов (PCL).

  • Проекты .NET Standard — это предпочтительный подход к совместному использованию кода .NET, дополнительные сведения о проектах .NET Standard и Xamarin.
  • Общие проекты активов используют один набор файлов и предлагают быстрый и простой способ совместного использования кода в решении и обычно использует директивы условной компиляции для указания путей кода для различных платформ, которые будут использовать его (дополнительные сведения см . в статье "Общие проекты").
  • Проекты PCL предназначены для определенных профилей, поддерживающих известный набор классов и функций BCL. Тем не менее, вниз к PCL заключается в том, что они часто требуют дополнительных архитектурных усилий для разделения конкретного кода профиля в собственные библиотеки.

На этой странице объясняется, как создать проект PCL, предназначенный для конкретного профиля, на который затем можно ссылаться несколькими проектами для конкретной платформы.

Что такое переносимая библиотека классов?

При создании проекта приложения или проекта библиотеки результирующая библиотека DLL ограничена работой на определенной платформе, для которую она создана. Это предотвращает запись сборки для приложения Windows, а затем повторно использовать ее в Xamarin.iOS и Xamarin.Android.

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

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

Функция .NET Framework приложения универсальной платформы Windows; Silverlight Windows Phone Xamarin
Основные сведения Y Y Y Y Y
LINQ Y Y Y Y Y
IQueryable Y Y Y 7.5 или выше Y
Сериализация Y Y Y Y Y
Заметки к данным 4.0.3 + Y Y Y

Столбец Xamarin отражает тот факт, что Xamarin.iOS и Xamarin.Android поддерживают все профили, отправленные в Visual Studio, и доступность функций в любых библиотеках, создаваемых вами, будет ограничена только другими платформами, которые вы выбираете для поддержки.

К ним относятся профили, которые являются сочетаниями:

  • .NET 4 или .NET 4.5
  • Silverlight 5
  • Windows Phone 8
  • приложения универсальной платформы Windows;

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

Льготы

  1. Централизованный общий доступ к коду — написание и тестирование кода в одном проекте, который может использоваться другими библиотеками или приложениями.
  2. Операции рефакторинга повлияют на весь код, загруженный в решение (переносимая библиотека классов и проекты для конкретной платформы).
  3. Проект PCL можно легко ссылаться на другие проекты в решении, или выходные сборки можно предоставить другим пользователям, чтобы ссылаться на их решения.

Недостатки

  1. Так как одна и та же переносимая библиотека классов используется для нескольких приложений, не удается ссылаться на библиотеки для конкретных платформ (например. Community.CsharpSqlite.WP7).
  2. Подмножество переносимой библиотеки классов может не включать классы, которые в противном случае будут доступны как в MonoTouch, так и в Mono для Android (например, DllImport или System.IO.File).

Примечание.

Переносимые библиотеки классов устарели в последней версии Visual Studio, а библиотеки .NET Standard рекомендуется вместо этого.

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

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

This diagram shows the architecture of a cross-platform application using a Portable Class Library to share code, but also using Dependency Injection to pass in platform-dependent features

пошаговое руководство по Visual Studio для Mac

В этом разделе описывается создание и использование переносимой библиотеки классов с помощью Visual Studio для Mac. Ознакомьтесь с разделом "Пример PCL" для полной реализации.

Создание PCL

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

  1. В диалоговом окне "Новый проект" выберите параметр "Переносимая библиотека многоплатформной > библиотеки>":

    Create a new PCL project

  2. При создании PCL в Visual Studio для Mac он автоматически настраивается с помощью профиля, который работает для Xamarin.iOS и Xamarin.Android. Проект PCL появится, как показано на этом снимке экрана:

    PCL project in the solution pad

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

Изменение параметров PCL

Чтобы просмотреть и изменить параметры PCL для этого проекта, щелкните проект правой кнопкой мыши и выберите " Параметры > сборки > " , чтобы просмотреть экран, показанный здесь:

PCL Project Options to set the profile

Нажмите кнопку "Изменить", чтобы изменить целевой профиль для этой переносимой библиотеки классов.

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

Работа с PCL

При написании кода в библиотеке PCL редактор Visual Studio для Mac распознает ограничения выбранного профиля и соответствующим образом настраивает параметры автоматического завершения. Например, на этом снимке экрана показаны параметры автоматического завершения System.IO с помощью профиля по умолчанию (Profile136), используемого в Visual Studio для Mac. Обратите внимание, что полоса прокрутки, указывающая, что отображается около половины доступных классов (на самом деле доступны только 14 классов).

Intellisense list of 14 classes in the System.IO class of a PCL

Сравните это с автоматическим завершением System.IO в проекте Xamarin.iOS или Xamarin.Android— доступны 40 классов, включая часто используемые классы, такие File как и Directory которые не находятся в профиле PCL.

Intellisense list of 40 classes in .NET Framework System.IO namespace

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

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

После создания проекта PCL можно добавить ссылку на нее из любого совместимого проекта приложения или библиотеки таким же образом, как и при добавлении ссылок. В Visual Studio для Mac щелкните правой кнопкой мыши узел "Ссылки" и выберите пункт "Изменить ссылки", а затем перейдите на вкладку "Проекты", как показано ниже.

Add a reference to a PCL via Edit References option

На следующем снимке экрана показана панель решения для примера приложения TaskyPortable, в которой показана библиотека PCL в нижней части и ссылка на библиотеку PCL в проекте Xamarin.iOS.

TaskyPortable sample solution showing PCL project

Выходные данные pcL (т. е. результирующая библиотека DLL сборки) также можно добавить в качестве ссылки на большинство проектов. Это делает PCL идеальным способом доставки кроссплатформенных компонентов и библиотек.

Пример PCL

Пример приложения TaskyPortable демонстрирует, как можно использовать переносимую библиотеку классов с Xamarin. Ниже приведены некоторые снимки экрана полученных приложений, работающих в iOS и Android:

Here are some screenshots of the resulting apps running on iOS, Android and Windows Phone

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

Структура решения показана ниже (в Visual Studio для Mac и Visual Studio соответственно):

The solution structure is shown here in Visual Studio for Mac and Visual Studio respectively

Так как код SQLite-NET содержит фрагменты, зависящие от платформы (для работы с реализациями SQLite в каждой разной операционной системе) для демонстрационных целей, он был рефакторингован в абстрактный класс, который можно скомпилировать в переносимой библиотеке классов, и фактический код, реализованный как подклассы в проектах iOS и Android.

TaskyPortableLibrary

Переносимая библиотека классов ограничена функциями .NET, которые она может поддерживать. Так как он компилируется для запуска на нескольких платформах, он не может использовать [DllImport] функциональные возможности, используемые в SQLite-NET. Вместо этого SQLite-NET реализуется как абстрактный класс, а затем ссылается на остальной части общего кода. Ниже показано извлечение абстрактного API:

public abstract class SQLiteConnection : IDisposable {

    public string DatabasePath { get; private set; }
    public bool TimeExecution { get; set; }
    public bool Trace { get; set; }
    public SQLiteConnection(string databasePath) {
         DatabasePath = databasePath;
    }
    public abstract int CreateTable<T>();
    public abstract SQLiteCommand CreateCommand(string cmdText, params object[] ps);
    public abstract int Execute(string query, params object[] args);
    public abstract List<T> Query<T>(string query, params object[] args) where T : new();
    public abstract TableQuery<T> Table<T>() where T : new();
    public abstract T Get<T>(object pk) where T : new();
    public bool IsInTransaction { get; protected set; }
    public abstract void BeginTransaction();
    public abstract void Rollback();
    public abstract void Commit();
    public abstract void RunInTransaction(Action action);
    public abstract int Insert(object obj);
    public abstract int Update(object obj);
    public abstract int Delete<T>(T obj);

    public void Dispose()
    {
        Close();
    }
    public abstract void Close();

}

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

TaskyAndroid и TaskyiOS

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

Эти проекты также содержат реализацию API абстрактной базы данных, которая работает на этой платформе. В iOS и Android ядро СУБД Sqlite встроено в операционную систему, поэтому реализация может использовать [DllImport] , как показано для обеспечения конкретной реализации подключения к базе данных. Ниже показан фрагмент кода реализации для конкретной платформы:

[DllImport("sqlite3", EntryPoint = "sqlite3_open")]
public static extern Result Open(string filename, out IntPtr db);

[DllImport("sqlite3", EntryPoint = "sqlite3_close")]
public static extern Result Close(IntPtr db);

Полную реализацию можно увидеть в примере кода.

Итоги

В этой статье кратко рассматриваются преимущества и недостатки переносимых библиотек классов, показано, как создавать и использовать PCL из Visual Studio для Mac и Visual Studio, и, наконец, ввело полный пример приложения —TaskyPortable, которое показывает PCL в действии.