PCL (Bibliotecas de classe portáteis)

Dica

As PCLs (Bibliotecas de Classes Portáteis) são consideradas preteridas nas versões mais recentes do Visual Studio. Embora você ainda possa abrir, editar e compilar PCLs para novos projetos, é recomendável usar bibliotecas do .NET Standard para acessar uma área de superfície de API maior.

Um componente fundamental da criação de aplicativos multiplataforma é poder compartilhar código em vários projetos específicos da plataforma. No entanto, isso é complicado pelo fato de que diferentes plataformas geralmente usam um subconjunto diferente da BCL (Biblioteca de Classes Base) do .NET e, portanto, são realmente criadas para um perfil de biblioteca .NET Core diferente. Isso significa que cada plataforma só pode usar bibliotecas de classes direcionadas ao mesmo perfil para que elas pareçam exigir projetos de biblioteca de classes separados para cada plataforma.

Há três abordagens principais para o compartilhamento de código que resolvem esse problema: projetos .NET Standard, Projetos de Ativo Compartilhado e projetos pcl (biblioteca de classes portátil).

  • Os projetos do .NET Standard são a abordagem preferencial para compartilhar código .NET, leia mais sobre projetos .NET Standard e Xamarin.
  • Os Projetos de Ativos Compartilhados usam um único conjunto de arquivos e oferecem uma maneira rápida e simples de compartilhar código em uma solução e geralmente emprega diretivas de compilação condicional para especificar caminhos de código para várias plataformas que o usarão (para obter mais informações, consulte o artigo Projetos Compartilhados).
  • Os projetos PCL têm como destino perfis específicos que dão suporte a um conjunto conhecido de classes/recursos BCL. No entanto, o lado inferior da PCL é que eles geralmente exigem esforços de arquitetura extra para separar o código específico do perfil em suas próprias bibliotecas.

Esta página explica como criar um projeto PCL direcionado a um perfil específico, que pode ser referenciado por vários projetos específicos da plataforma.

O que é uma biblioteca de classes portátil?

Quando você cria um Projeto de Aplicativo ou um Projeto de Biblioteca, a DLL resultante fica restrita a trabalhar na plataforma específica para a qual ela é criada. Isso impede que você escreva um assembly para um aplicativo do Windows e, em seguida, reutilize-o no Xamarin.iOS e no Xamarin.Android.

No entanto, ao criar uma Biblioteca de Classes Portátil, você pode escolher uma combinação de plataformas em que deseja que seu código seja executado. As opções de compatibilidade que você faz ao criar uma Biblioteca de Classes Portátil são convertidas em um identificador de "Perfil", que descreve quais plataformas a biblioteca dá suporte.

A tabela a seguir mostra alguns dos recursos que variam de acordo com a plataforma .NET. Para escrever um assembly PCL que tem a garantia de ser executado em dispositivos/plataformas específicos, basta escolher qual suporte é necessário ao criar o projeto.

Recurso .NET Framework Aplicativos UWP Silverlight Windows Phone Xamarin
Núcleo S S S S S
LINQ S S S S S
IQueryable S S S 7.5 + S
Serialização S S S S S
Anotações de dados 4.0.3 + S S S

A coluna Xamarin reflete o fato de que o Xamarin.iOS e o Xamarin.Android dão suporte a todos os perfis enviados com o Visual Studio, e a disponibilidade de recursos em todas as bibliotecas criadas só será limitada pelas outras plataformas que você escolher para dar suporte.

Isso inclui perfis que são combinações de:

  • .NET 4 ou .NET 4.5
  • Silverlight 5
  • Windows Phone 8
  • Aplicativos UWP

Você pode ler mais sobre os recursos dos diferentes perfis no site da Microsoft e ver o resumo do perfil PCL de outro membro da comunidade, que inclui informações de estrutura com suporte e outras anotações.

Benefícios

  1. Compartilhamento de código centralizado – escrever e testar código em um único projeto que pode ser consumido por outras bibliotecas ou aplicativos.
  2. As operações de refatoração afetarão todo o código carregado na solução (a Biblioteca de Classes Portátil e os projetos específicos da plataforma).
  3. O projeto PCL pode ser facilmente referenciado por outros projetos em uma solução ou o assembly de saída pode ser compartilhado para que outras pessoas referenciem em suas soluções.

Desvantagens

  1. Como a mesma Biblioteca de Classes Portátil é compartilhada entre vários aplicativos, bibliotecas específicas da plataforma não podem ser referenciadas (por exemplo, Community.CsharpSqlite.WP7).
  2. O subconjunto Da Biblioteca de Classes Portátil pode não incluir classes que, de outra forma, estariam disponíveis no MonoTouch e no Mono para Android (como DllImport ou System.IO.File).

Observação

As bibliotecas de classes portáteis foram preteridas na versão mais recente do Visual Studio, e as bibliotecas do .NET Standard são recomendadas.

Até certo ponto, ambas as desvantagens podem ser contornadas usando o padrão Provider ou a Injeção de Dependência para codificar a implementação real nos projetos de plataforma em relação a uma interface ou classe base definida na Biblioteca de Classes Portátil.

Este diagrama mostra a arquitetura de um aplicativo multiplataforma usando uma Biblioteca de Classes Portátil para compartilhar código, mas também usando a Injeção de Dependência para passar recursos dependentes da plataforma:

Este diagrama mostra a arquitetura de um aplicativo multiplataforma usando uma Biblioteca de Classes Portátil para compartilhar código, mas também usando a Injeção de Dependência para passar recursos dependentes da plataforma

passo a passo Visual Studio para Mac

Esta seção explica como criar e usar uma Biblioteca de Classes Portátil usando Visual Studio para Mac. Consulte a seção Exemplo de PCL para obter uma implementação completa.

Criando uma PCL

Adicionar uma Biblioteca de Classes Portátil à sua solução é muito semelhante à adição de um projeto de Biblioteca regular.

  1. Na caixa de diálogo Novo Projeto, selecione a opção Biblioteca Portátil biblioteca > multiplataforma>:

    Criar um novo projeto pcl

  2. Quando uma PCL é criada no Visual Studio para Mac ela é configurada automaticamente com um Perfil que funciona para Xamarin.iOS e Xamarin.Android. O projeto PCL será exibido conforme mostrado nesta captura de tela:

    Projeto PCL no painel de solução

A PCL agora está pronta para que o código seja adicionado. Ele também pode ser referenciado por outros projetos (projetos de aplicativo, projetos de biblioteca e até mesmo outros projetos pcl).

Editando configurações de PCL

Para exibir e alterar as configurações de PCL deste projeto, clique com o botão direito do mouse no projeto e escolha Opções > Compilar > Geral para ver a tela mostrada aqui:

Opções de projeto de PCL para definir o perfil

Clique em Alterar... para alterar o perfil de destino desta biblioteca de classes portátil.

Se o perfil for alterado depois que o código já tiver sido adicionado à PCL, é possível que a biblioteca não seja mais compilada se o código fizer referência a recursos que não fazem parte do perfil recém-selecionado.

Trabalhando com uma PCL

Quando o código é escrito em uma biblioteca PCL, o editor de Visual Studio para Mac reconhecerá as limitações do perfil selecionado e ajustará as opções de preenchimento automático adequadamente. Por exemplo, esta captura de tela mostra as opções de preenchimento automático para System.IO usando o perfil padrão (Profile136) usado em Visual Studio para Mac – observe a barra de rolagem que indica que cerca de metade das classes disponíveis são exibidas (na verdade, há apenas 14 classes disponíveis).

Lista do IntelliSense de 14 classes na classe System.IO de uma PCL

Compare isso com o System.IO preenchimento automático em um projeto Xamarin.iOS ou Xamarin.Android – há 40 classes disponíveis, incluindo classes comumente usadas como File e Directory que não estão em nenhum perfil PCL.

Lista do Intellisense de 40 classes no namespace .NET Framework System.IO

Isso reflete a compensação subjacente do uso de PCL – a capacidade de compartilhar código perfeitamente em várias plataformas significa que determinadas APIs não estão disponíveis para você porque elas não têm implementações comparáveis em todas as plataformas possíveis.

Usando PCL

Depois que um projeto PCL for criado, você poderá adicionar uma referência a ele de qualquer projeto compatível de Aplicativo ou Biblioteca da mesma maneira que normalmente você adiciona referências. Em Visual Studio para Mac, clique com o botão direito do mouse no nó Referências e escolha Editar Referências e alterne para a guia Projetos, conforme mostrado:

Adicionar uma referência a um PCL por meio da opção Editar Referências

A captura de tela a seguir mostra o painel Solução para o aplicativo de exemplo TaskyPortable, mostrando a biblioteca PCL na parte inferior e uma referência a essa biblioteca PCL no projeto Xamarin.iOS.

Solução de exemplo TaskyPortable mostrando o projeto PCL

A saída de uma PCL (ou seja, a DLL do assembly resultante) também pode ser adicionada como uma referência à maioria dos projetos. Isso torna a PCL uma maneira ideal de enviar componentes e bibliotecas multiplataforma.

Exemplo de PCL

O aplicativo de exemplo TaskyPortable demonstra como uma Biblioteca de Classes Portátil pode ser usada com o Xamarin. Aqui estão algumas capturas de tela dos aplicativos resultantes em execução no iOS e no Android:

Aqui estão algumas capturas de tela dos aplicativos resultantes em execução no iOS, Android e Windows Phone

Ele compartilha várias classes de dados e lógicas que são código puramente portátil e também demonstra como incorporar requisitos específicos da plataforma usando a Injeção de Dependência para a implementação do banco de dados SQLite.

A estrutura da solução é mostrada abaixo (no Visual Studio para Mac e no Visual Studio, respectivamente):

A estrutura da solução é mostrada aqui no Visual Studio para Mac e no Visual Studio, respectivamente

Como o código SQLite-NET tem partes específicas da plataforma (para trabalhar com as implementações do SQLite em cada sistema operacional diferente) para fins de demonstração, ele foi refatorado em uma classe abstrata que pode ser compilada em uma Biblioteca de Classes Portátil e o código real implementado como subclasses nos projetos iOS e Android.

TaskyPortableLibrary

A Biblioteca de Classes Portátil é limitada nos recursos do .NET aos quais ela pode dar suporte. Como ele é compilado para ser executado em várias plataformas, ele não pode usar [DllImport] a funcionalidade usada no SQLite-NET. Em vez disso, o SQLite-NET é implementado como uma classe abstrata e referenciado pelo restante do código compartilhado. Um extrato da API abstrata é mostrado abaixo:

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();

}

O restante do código compartilhado usa a classe abstrata para "armazenar" e "recuperar" objetos do banco de dados. Em qualquer aplicativo que use essa classe abstrata, devemos passar uma implementação completa que forneça a funcionalidade real do banco de dados.

TaskyAndroid e TaskyiOS

Os projetos de aplicativos iOS e Android contêm a interface do usuário e outros códigos específicos da plataforma usados para conectar o código compartilhado na PCL.

Esses projetos também contêm uma implementação da API de banco de dados abstrata que funciona nessa plataforma. No iOS e no Android, o mecanismo de banco de dados Sqlite é integrado ao sistema operacional, portanto, a implementação pode ser usada [DllImport] conforme mostrado para fornecer a implementação concreta da conectividade do banco de dados. Um trecho do código de implementação específico da plataforma é mostrado aqui:

[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);

A implementação completa pode ser vista no código de exemplo.

Resumo

Este artigo discutiu brevemente os benefícios e armadilhas das Bibliotecas de Classes Portáteis, demonstrou como criar e consumir PCLs de dentro do Visual Studio para Mac e do Visual Studio; e finalmente introduziu um aplicativo de exemplo completo – TaskyPortable – que mostra um PCL em ação.