O Prism é um framework para desenvolvimento utilizando o padrão MVVM. Ele se encaixa muito bem no Xamarin Forms e possui diversos métodos já prontos que nos auxiliam a realizar diversas tarefas como navegação, bindings entre outros e ajuda a deixar a aplicação mais testável.
O Prism é open source e você pode acompanhar as issues, commites e todo o codigo fonte no GitHub.
Neste post irei tratar da migração da versão 6 para a 7. Caso você queira saber mais sobre o Prism clique aqui
O que há de novo?
Entre a disponibilização da ultima versão estável do Prism, 6.3.0, para a versão 7, se passaram 10 meses. Neste periodo a equipe que mantém o Prism colheu diversos feedbacks com a comunidade, corrigindo erros, aceitando contribuições de código da comunidades e desenvolvendo muitas melhorias.
Neste nova versão do Prism, muita coisa mudou. Existem alguns breaking changes que precisam ser alterados no código e você pode ver mais sobre eles nas releases notes clicando aqui.
Entre as melhorias, podemos destacar o suporte a .Net Standart, mudança na navegação de páginas com abas, remoção de páginas da stack de navegação e abstração do container de dependências.
Atualizando tudo
O primeiro passo para fazer a atualização é atualizar os pacotes nuget Prism.Forms, Prism.Unity e Prism.Core para a versão 7. Após feito isto, vc irá ver que seu projeto não compila mais..
Vamos realizar algumas mudanças para adequar a aplicação a nova versão do Prism, a maior parte destas mudanças serão realizadas no App.xaml.cs.
IPlatformInitializer
O primeiro passo e alterar o namespace de IPlatformInitializer de Microsoft.Practices.Unity para Prism. Isto é necessário devido a abstração do container e remoção da dependencia direta do container do Prism.
Você precisará realizar a mesma alteração nos Initializers que criamos em cada plataforma que também herdam de IPlatformInitializer (AndroidInitializer e iOSInitializer)
RegisterTypes – Registrando as páginas
Após isto, vamos refatorar o método RegisterTypes. Na versão 6 do Prism este método era implementado sem receber nenhum parametro. Na versão 7 ele passa a ter o parametro containerRegistry do tipo IContainerRegistry . Esta mudança ocorre para que o Prism fique independente de plataforma de container que a pessoa desenvolvedora escolher para usar. Desta forma, o registro de págians e a localização de ViewModels ficará a cargo do Prism. Repare que uma nova namespace foi adicionada a Prism.Ioc. Esta separação também ajuda em manter as responsabilidades do Prism e do Container de depencias isoladas.
Portanto, o registro de páginas e view models agora ficará a cargo do método RegisterForNavigation do objeto containerRegistry
Registrando os tipos
Após registradas as páginas e view models, vamos registrar nossas interfaces. Vou considerar o uso do container de injeção de dependencias Unity.
Atualize o pacote do Unity para a versão 5.5.5 ou maior.
Após ataulizar o pacote do Unity, vamos voltar a página App.xaml.cs para alterar o registro das interfaces. Até o momento, as interfaces estavam sendo registradas no objeto Container e caso quisessemos acessar o container em outro lugar do código prisavamos de uma propriedade do tipo IUnityContainer que recebia o objeto Container ao fim de todos os registros.
O registro dos nossos objetos no container de dependências será feito através container que é retornado pelo método GetContainer() do obejeto containerRegistry. Este método irá retornar a instância atual do container para manipulação. O objeto Container que era utilizado anteriormente para esta função, na versão 7 é apenas para resolver tipos e não registrá-los.
As dependências containuarão sendo registradas pelo método RegisterType como ocorria na versão 6, mas através do container retornado pelo método GetContainer()
Caso você precise acessar o container de fora da classe App.xaml.cs, crie uma nova variável do tipo IUnityContainer e atribua o retorno de GetContainer a ela. Faça esta atribuição ao fim de todos os registros de tipos para garantir que você está com a versão da instãncia do container que contém todas as dependências registradas. Veja abaixo:
Criando a variável IUnityContainer
public static IUnityContainer _unityContainer { get; set; }
Atribuindo o container atual a variavel exposta para acesso externo
containerRegistry.GetContainer().RegisterType(typeof(ICurrentDateService), typeof(CurrentDateService));
_unityContainer = containerRegistry.GetContainer() as UnityContainer;
Existem diversas outras mudanças que aconteceram nesta troca de versão. Neste post tentei citar o necessário para fazer sua aplicação rodar. Se você quiser ler mais sobre a atualização e mais coisas que você pode migrar no seu código fonte, não deixe de conferir o artigo da XamGirl e do Brian Lagunas.
Todas as mudanças também estão disponíveis nos Release Notes do Prism, veja aqui
App.xaml.cs antes da atualização
using Microsoft.Practices.Unity;
using Prism.Unity;
using UpdatePrism.ApplicationServices;
using UpdatePrism.ApplicationServices.Interfaces;
using Xamarin.Forms;
namespace UpdatePrism
{
public partial class App : PrismApplication
{
public static IUnityContainer _unityContainer { get; set; }
public App(IPlatformInitializer initializer) : base(initializer) { }
protected override void OnInitialized()
{
InitializeComponent();
MainPage = new NavigationPage(new MainPage());
}
protected override void RegisterTypes()
{
//Register Types
Container.RegisterType(typeof(ICurrentDateService), typeof(CurrentDateService));
//Register Pages
Container.RegisterTypeForNavigation<MainPage, MainPageViewModel>();
//Set Container to Unity Container for use out of App class
_unityContainer = Container;
}
}
}
App.xaml.cs depois da atualização
using Prism;
using Prism.Ioc;
using Prism.Unity;
using Unity;
using UpdatePrism.ApplicationServices;
using UpdatePrism.ApplicationServices.Interfaces;
using Xamarin.Forms;
namespace UpdatePrism
{
public partial class App : PrismApplication
{
public static IUnityContainer _unityContainer { get; set; }
public App(IPlatformInitializer initializer) : base(initializer) { }
protected override void OnInitialized()
{
InitializeComponent();
MainPage = new NavigationPage(new MainPage());
}
protected override void RegisterTypes(IContainerRegistry containerRegistry)
{
//Register Types
containerRegistry.RegisterForNavigation<MainPage, MainPageViewModel>();
//Register Pages
containerRegistry.GetContainer().RegisterType(typeof(ICurrentDateService), typeof(CurrentDateService));
//Set Container to Unity Container for use out of App class
_unityContainer = containerRegistry.GetContainer() as UnityContainer;
}
}
}
Você pode baixar o código fonte do exemplo deste post no meu GitHub.
Linker?
Se você usava Link all / Sdk and User assemblys no seu projeto, após a migração ele também terá parado de funcionar.
Caso você não conheça o funcionamento do Linker e como ele pode ajudar o app, leia o excelente artigo do Mahmoud Ali clicando aqui
Atualizar o arquivo de ignore do linker é um processo moroso e complicado. Após algum tempo, cheguei nesta configuração:
<?xml version="1.0" encoding="UTF-8" ?>
<linker>
<assembly fullname="Prism.Forms">
<type fullname="Prism.Common.ApplicationProvider" preserve="all" />
<type fullname="Prism.Services.PageDialogService" preserve="all" />
<type fullname="Prism.Services.DeviceService" preserve="all" />
<type fullname="Prism.Ioc*" preserve="all" />
<type fullname="Prism.Modularity*" preserve="all" />
<type fullname="Prism.Navigation*" preserve="all" />
<type fullname="Prism.Behaviors.PageBehaviorFactory" preserve="all">
<method name=".ctor" />
</type>
<type fullname="Prism.Services.DependencyService" preserve="all">
<method name=".ctor" />
</type>
</assembly>
<assembly fullname="Prism">
<type fullname="Prism.Navigation*" preserve="all" />
<type fullname="Prism.Logging.EmptyLogger" preserve="all">
<method name=".ctor" />
</type>
</assembly>
<assembly fullname="Unity.Abstractions">
<type fullname="*" />
</assembly>
<assembly fullname="Unity.Container">
<type fullname="*" />
</assembly>
</linker>
Com estes arquivos sendo ignorados o app ficou um pouco menor do que antes da atualização de versão e rodou normalmente.
Conclusão
A atualização do Prism permitiu maior flexibilidade na escolha do container de dependencias e também atualizou diversos recursos que estavam obsoletos na versão 6. Trouxe muitas melhorias como navagação de abas e o suporte a .net standart. Um problema da atualização foi a grande quantidade de breaking changes, mas com paciência conseguimos contorná-los.
Imagem utilizada no post Pixabay
—
#Ubuntu
Referências
Comentários