Get started with Prism

Prism – Composite Application Guidance is designed to build enterprise-level client applications in a modular fashion. It helps to build composite applications as loosely coupled modules that can be independently developed and deployed. In this article we will see how to get started using Composite Application Guidance.

Download Source code here

Download Composite Application Guidance


Prism

Prism – Composite Application Guidance is designed to build enterprise-level client applications in a modular fashion. It helps to build composite applications as loosely coupled modules that can be independently developed and deployed.



Prism helps us to achieve the following

1. Modularity

Modularity is a general systems concept that defines the degree at which a system's components can be separated and recombined. Prism is designed in such a way that it supports modular design and the system can be architected as a set of loosely coupled modules.

2. UI Composition

UI composition is the capability to design the interface from different components and to achieve this, Prism introduces the concept of regions. Controls can be marked with regions and modules can then load the views in these regions.

3. Dependency Injection

Dependency injection, a term first coined by Martin Fowler, is injecting objects in the class without the class being responsible for creating the objects. Prism applications are loosely coupled applications and the components need a mechanism to interact with each other; dependency injection container serves this purpose. It allows for registration of modules and classes which are then used for providing instances of these classes and manage their lifetime based on the configuration. Thus responsibility gets transferred from the component to container. Under the hood Prism relies heavily on the Unity Application block to achieve this.


Unity Application Block

The Unity Application Block is based on Inversion of control pattern and dependency injection pattern. It is a lightweight extensible dependency injection container with support for constructor, property, and method call injection.

It simplifies application code by providing simplified object creation. It allows developers to specify dependencies at runtime or in the configuration.

Unity is used throughout Prism to inject classes and is responsible to create instances and provide references to them when required.

We have visited a few concepts and now
we will get down to programming and visit concepts as and when they come our way. The basic application which we will be visiting consists of two parts.

  • Create Shell

  • Create Module

1. Create Shell

- Let us start creating a simple Wpf application ‘WpfShell’ using Visual Studio. The following files App.xaml, Window.xaml and corresponding cs files are generated. The part of code in App.xaml that is of interest is StartupUri="Window1.xaml". This is a Start-up Uniform Resource Identifier (URI) which is responsible for launching the main window.

<Application x:Class="WpfShell.App"

xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

StartupUri="Window1.xaml">

<Application.Resources>

</Application.Resources>

</Application>


We will have an application that will show an empty screen but to achieve the same result in Prism we need to do a few steps.

We will require the following Composite Application Library and Unity Application Block assemblies:

  • Microsoft.Practices.Composite.dll

    This assembly contain non UI specific components like modularity, logging and communication services, and several core interfaces’ definitions.

  • Microsoft.Practices.Composite. Presentation.dll

    This assembly contains components that relate to the UI specific elements like commands, regions, and events and includes CompositeCommand, DelegateCommand, CompositePresentationEvent, and RegionManager.

  • Microsoft.Practices.Composite.UnityExtensions.dll

    This assembly provides components to use the Unity Application Block with the Composite Application Guidance. These components include UnityBootstrapper and UnityServiceLocatorAdapter.

  • Microsoft.Practices.Unity.dll and Microsoft.Practices.ObjectBuilder2.dll

    These assemblies enable you to use the Unity Application Block in your application. By default, applications built with the Composite Application Guidance use the Unity Application Block.

The Composite Application Library ships as source code, which means we need to compile it to get the Composite Application Library assemblies . The general convention is to compile the assemblies and move them to a separate folder under the solution root folder.

- Let us now rename Window1.xaml to Shell.xaml and also rename the corresponding class.

Note: We can keep it as Window1.xaml or give it some other name but this is the general convention that is followed in Prism.

Bootstrapper

Just like the App.xaml and startup Uniform Resource Identifier (URI) that is responsible to launch the main window, Bootstrapper has the responsibility to create the main window i.e. the shell and is responsible for the initialization of the application.

Application built on Prism will contain a Bootstrapper class that inherits from the abstract class UnityBootstrapper which uses the Unity container for initialization. Many of its methods are virtual and we need to override these methods wherever required.

Following are the stages in the bootstrapping process.





Configure the Container

Prism contains a dependency injection container that is responsible for instantiating classes and managing their lifetimes. During this phase, container is created and several core services are registered.


Configure the Region Mappings

The default region adapter mappings are registered in this stage, which are then used by the region manager to associate the correct adapters for XAML-defined regions.

Create the shell

During this stage, the Unity container is used to get the instance of the Shell and the shell is displayed.

Initialize the Module

In this stage the Unity container is used to get the instances of various Modules and they are later initialized.

- We will now add the Bootstrapper class. The following is the code for the Bootstraper. The Unity container is used to resolve the shell and show it.


internal
class Bootstrapper : UnityBootstrapper
{

protected override DependencyObject CreateShell()
{

Shell shell = this.Container.Resolve<Shell>();

shell.Show();

return
shell;

}

protected override void InitializeModules()
{

}

}

We also need to add reference to the following assemblies

  • Microsoft.Practices.Unity.dll
  • Microsoft.Practices.Composite.UnityExtensions.dll


We will now delete
StartupUri="Window1.xaml" in App.xaml code and add the following code in App.xaml.cs file.

public partial class App : Application
{
protected override void OnStartup(StartupEventArgs e)
{

base.OnStartup(e);

Bootstrapper bootStrapper = new Bootstrapper();

bootStrapper.Run();

}
}

In the Startup method, we call the base OnStartup and then call the run method of the Bootstrapper.


If you run the application now, Prism application will display an empty window.

Regions

The advantage of Prism is to host views from different modules in the different regions defined in shell or other views. Regions are the placeholders for content and host visual elements. Hence, we will replace the Grid with ItemsControl and set the attached property cal:RegionManager.RegionName to "MainRegion".


<
Window
x
:Class="WpfShell.Shell"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
mlns:cal="http://www.codeplex.com/CompositeWPF"
Title="Shell" Height="300" Width="300">
<ItemsControl Name="MainRegion" cal:RegionManager.RegionName="MainRegion" />
</Window>

We need to add reference to the following

  • Microsoft.Practices.Composite.dll
  • Microsoft.Practices.Composite.Presentation.dll

Following are the steps in brief

1) Create WPF application project ‘WpfShell

2) Add reference to Composite Application Library and Unity Application Block assemblies

3) Rename Window1.xaml to Shell.xaml and rename its class too.

4) Add Bootstrapper class with CreateShell method and empty InitializeModules.

5) Delete StartupUri="Window1.xaml" in App.xaml

6) Add OnStartup(StartupEventArgs e) method to app class in App.xaml.cs

7) Replace the Grid with ItemsControl and set the attached property cal:RegionManager.RegionName to "MainRegion".


2. Create Module

Modules assist in implementing modularity and promote separation of concerns. They are independently developed and deployed; also, they are discovered and loaded at runtime.

- In order to add modules let us start by adding a WPF User Control Library project ‘WpfProducts’ to the solution.

- Now let us rename UserControl1.xaml to ProductsView.xaml and rename the corresponding class also.

Further add reference to the following assemblies

  • Microsoft.Practices.Composite.dll
  • Microsoft.Practices.Composite.Presentation.dll

The modules project that we will be building will have a class that implement IModule which has single method void Initialize(). In this method we will add the ProductsView to the region.

public class ProductsModule:IModule
{

private readonly IRegionManager _regionManager;

public ProductsModule(IRegionManager regionManager)
{
_regionManager = regionManager;
}

public void Initialize()
{
_regionManager.Regions["MainRegion"].Add(new ProductsView());
}

}

Constructor injection

public ProductsModule(IRegionManager regionManager)

The above code is a an example of Constructor Injection. When we create an instance of an object, Unity will automatically detect the appropriate constructor with maximum parameters and create the instance for each parameter having appropriate registrations and using appropriate mappings.

Now add reference to the Products project to the WpfShell project and we will need to add the module initialization code in InitializeModules method.

internal class Bootstrapper : UnityBootstrapper
{
protected override DependencyObject CreateShell()
{

Shell shell = Container.Resolve<Shell>();

shell.Show();

return shell;

}

protected override void InitializeModules()
{

IModule productsModule = this.Container.Resolve<ProductsModule>();

productsModule.Initialize();

}

}

Resolve

Container.Resolve<ProductsModule>();

We can register a mapping between the base class or interface type and the concrete class, and later we can call the Resolve method to get the instance of that type. Unity will create an instance of the class on the first request, and then it returns the same instance in response to all subsequent requests.

In our application we have a direct reference to the Products Module in the WpfShell we can be avoid direct reference by dynamically loading the modules on demand.


Following are the steps in brief

1) Add WPF User Control Library project ‘WpfProducts’ to the solution.

2) Rename UserControl1.xaml to ProductsView.xaml and rename the corresponding class also
3) Add an interface IProductsView and ensure that the ProductsView control implements it.

3) Add reference to the following assemblies

  • Microsoft.Practices.Composite.dll
  • Microsoft.Practices.Composite.Presentation.dll

4) Add ProductsModule modules class that implement IModule and add the ProductsView to the region in Initialize method.

5) Add the module initialization code in InitializeModules method of the Bootstrapper.


Thus, we can see that Prism uses the Unity application to support loosely coupled modules that can be independently developed and deployed.

The module can be then  be organised into Models, Views, Services, Presenters and Controllers. Also Prism provides event and command mechanism to communicate between loosely couple modules and these are topics of their own.

By Stevan Rodrigues   Popularity  (2582 Views)
Biography - Stevan Rodrigues
Stevan Rodrigues is Senior Software Developer presently working in Australia on WPF, WCF, Workflow, Prism and the .Net 3.5 Framework. He worked as a Technical Architect in India, and as Team Lead and various profiles in Dubai, UAE. Stevan is a Microsoft Certified Solutions Developer in .Net(MCSD.Net Early Achiever – one among the first 2500 worldwide), Microsoft Certified Application Developer in .Net – MCAD.Net (Charter Member - one among the first 5000 developers worldwide).