Aplicações Compostas com o Prism v2.0 : Um "Hello World" para começar.

Olá pessoal, tudo certo?

Atualmente, estou envolvido num projeto que avalia uma interface de composição e seus desafios. Existem diversos aspectos de arquitetura envolvidos nesse tipo de interface, como:

  • Suportar diferentes fontes de dados e serviços;
  • Utilizar patterns de composição para seus diversos componentes de tela;
  • Permitir o desenvolvimento simultâneo de seus componentes;
  • Suportar as novas necessidades de usabilidade e flexibilidade em interfaces UX;
  • Tratar layouts dinâmicos;
  • Tratar eventos e subscrição de eventos;

Para atender esses requisitos, existem diversos patterns aplicáveis, como:

  • Composite User Interface patterns: Composite and Composite View, Comando e Adaptadores;
  • Modularity patterns: Separated Interface and Plug In, Service Locator, Event Aggregator e Façades;
  • Testability patterns: Inversion of Control, Separated Presentation, etc.

Como alternativa na plataforma Microsoft estou usando o PRISM v2.0 - Composite Application Guidance for WPF and Silverlight 2.0, anunciado recentemente, veja aqui.

image

Assim, os próximos posts serão dedicados ao PRISM v2.0 e seus recursos.

Para começar, a figura ao lado apresenta a pilha de componentes do PRISM, que executa sobre o .NET 3.5 e os recursos do WPF - Windows Presentation Foundation.

Entre os componentes principais citamos:
o Unity Application Block, responsável pela infra-estrutura para inversão de controle e tratamento de containers; o Unity Extensions Composite Application Library, que disponibiliza os recursos da Unity no ambiente de programação do PRISM; e a própria Composite Application Library (CAL) , que encapsula esses recursos para o desenvolvedor PRISM.

Sobre a CAL, criamos nossos módulos e shell interface para a aplicação de composição.

Já no desenvolvimento de nossos módulos e elementos de tela, a CAL oferece o seguinte conjunto de recursos:

  • Bootstrapper
  • Module
  • Services & Containers
  • Regions
  • Views
  • Events
  • Commands

Seu primeio projeto com o PRISM v2.0

Vejamos um primeiro projeto com o PRISM. O pacote possui diversos projetos prontos que são boas dicas de estudo, entre eles, vários Quick Starts sobre cada um dos componentes da CAL. Vamos olhar hoje o Quick Start "Hello World". Ele se encontra instalado na pasta abaixo:

C:\[PRISM V2.0]\Quickstarts\Hello World\HelloWorld.Desktop

Abrindo o QuickStart "Hello World", você terá a seguinte solução no Visual Studio:

image

Na figura ao lado, vemos 1 pasta para os componentes da CAL (Composite .Desktop, Composite.Presentation.Desktop e Composite.UnityExtensions.Desktop), assim como 2 projetos na solução:

  • HelloWorld.Desktop - Projeto que implementa a interface principal, sendo também o ponto de entrada da aplicação;
  • HelloWorldModule - Projeto do módulo de visualização, que fará parte da interface principal. Em soluções maiores, teremos vários projetos de módulos, cada um implementando uma View ou Views de composição.

Portanto, uma solução com o PRISM terá no mínimo 2 projetos: a interface principal (sendo o ponto de entrada) e um módulo de visualização.

Quando olhamos o projeto do HelloWorldModule, notamos que nenhuma referência é feita para o projeto Desktop. Ao mesmo tempo, temos uma pasta de View(s) presente no projeto, implementando os componentes de tela do módulo. Uma View é na verdade um User Control em WPF que será apresentado na interface shell, como vemos abaixo:

image

Em XAML, esse User Control aparece assim:

    1: <UserControl x:Class="HelloWorldModule.Views.HelloWorldView"
    2:     xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation"
    3:     xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml">
    4:     <Grid>
    5:         <TextBlock Text="Hello World - Arquitetura de Soluções" Foreground="Green" HorizontalAlignment="Center" VerticalAlignment="Center" FontFamily="Calibri" FontSize="24" FontWeight="Bold"></TextBlock>
    6:     </Grid>
    7: </UserControl>

Encapsulando essa View no Módulo HelloWorld, vemos a classe HelloWorldModule, apresentada a seguir a partir do arquivo "HelloWorldModule.cs". Note que através dessa classe, relacionamos as views presentes no módulo, assim como a região que usaremos na interface principal para apresentação da view:

    1: using Microsoft.Practices.Composite.Modularity;
    2: using Microsoft.Practices.Composite.Regions;
    3:  
    4: namespace HelloWorldModule
    5: {
    6:     public class HelloWorldModule : IModule
    7:     {
    8:         private readonly IRegionViewRegistry regionViewRegistry;
    9:  
   10:         public HelloWorldModule(IRegionViewRegistry registry)
   11:         {
   12:             this.regionViewRegistry = registry;   
   13:         }
   14:  
   15:         public void Initialize()
   16:         {
   17:             regionViewRegistry.RegisterViewWithRegion("MainRegion", typeof(Views.HelloWorldView));
   18:         }
   19:     }
   20: }

Esse projeto compilado deverá gerar a biblioteca "HelloWorldModule.dll".

Olhando o projeto HelloWorld.Desktop presente na solução, vemos uma interface principal chamada Shell, que define a MainRegion, container para os vários módulos da solução.

image

O código XAML da Shell principal é dado a seguir:

    1: <Window x:Class="HelloWorld.Shell"
    2:     xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation"
    3:     xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml"
    4:     xmlns:cal="https://www.codeplex.com/CompositeWPF"
    5:     Title="Hello World" Height="195" Width="316">
    6:     <ItemsControl Name="MainRegion" cal:RegionManager.RegionName="MainRegion" />
    7: </Window>

No XAML acima vemos a definição do MainRegion, através da chamada cal:RegionManager.RegionName = "MainRegion". Nesse ponto, fazemos a associação da região para visualização do módulo criado.

Finalmente, o projeto HelloWorld.Desktop implementa uma classe importante chamada "Bootstrapper". Ela é o ponto de entrada da CAL na aplicação, sendo responsável pela enumeração e carga dos módulos participantes da solução.

No código abaixo, vemos o método GetModuleCatalog(), onde o módulo HelloWorldModule é chamado:

    1: namespace HelloWorld
    2: {
    3:     class Bootstrapper : UnityBootstrapper
    4:     {
    5:         protected override DependencyObject CreateShell()
    6:         {
    7:             Shell shell = new Shell();
    8:             shell.Show();
    9:             return shell;
   10:         }
   11:  
   12:         protected override IModuleCatalog GetModuleCatalog()
   13:         {
   14:             ModuleCatalog catalog = new ModuleCatalog()
   15:                 .AddModule(typeof(HelloWorldModule.HelloWorldModule));
   16:             return catalog;
   17:         }
   18:  
   19:         
   20:     }
   21: }

Uma vez compilado, o projeto HelloWorld.Desktop deverá gerar o executável "HelloWorld.exe" , que consome o módulo HelloWorldModule.dll.

Ao final, a aplicação executada apresenta a seguinte interface:

image

Como exercício sobre esse projeto, execute passo-a-passo a solução e verifique a ordem de disparo de cada um dos componentes da CAL. Você verá a primeira chamada para a class App : Application, seguida pela class Bootstrapper : UnityBootstrapper, etc. Vale conferir.

Nos próximos posts, vamos falar de cada um desses componentes, enquanto percorremos os HOW TO'S, Quick Starts e demais artigos presentes no Prism v2.0.

Por enquanto é só! Até o próximo post :)

Waldemir.