Sunday, June 30, 2013

Microsoft PRISM Modularity with WPF

Download Source Code Here

PRISM framework is specially target  for large scale application (But you can use this for small scale application too. But complexity is high).You can use prism framework  with WPF, Silverlight, Windows Phone and also with Windows store app (You have to use PRISM for windows run time ).

Main  4 Features of Prism.
    1. Modularity : You can developed the application as modules using class libarary and get all of them      togther during the run time.
    2. Region : This concept is similar to the ASP.NET master pages. Here you can define place holders and you can dynamically load view into these regions(place holders).
    3. Command : Prism command are implement using ICommand interface. Prims has inbuilt command called DelegateCommand. You can implement this DelegateCommand in you view -model and then You can bind the command with view (Nomarly with button).
    4. Event : To communicate between loosely couple component we can use event. You can use PRISM EventAggregator to these type of communication.

Why you should use PRISM ?
Just imagine that you want to develop application which is targeting HR handing,Financial handling ,etc. Without using framework like PRISM you can develop this application.No issue. But if you want to develop this application as  
 1. Separate modules.
 2. Module should be loosely couple with each other.
 3. Support for testability.
 4. Support for maintainability.
 5. Support for extendibility.
Then you should use framework like PRISM.Because that's what prism framework designed and developed for by Microsoft.

Before Jump into the development I assume that you have fair knowledge of following technologies.

1.  WPF
2.  MVVM design pattern
3.  Dependency injection design pattern.

Also you need to download  the Latest version of prism framework from Microsoft. After download you can extract libraries into a separate folder.

Our Example

Business Scenario :

Lets imagine our application has two main function.
  1. Display employee information
  2. Display product information

To demonstrate the PRISM capabilities I'm going to implement these two function in two different modules.Also For Implement the business Logic I will implement the another module called repository module.

So Let's start the development now.

1. First Open the VS2012 and create new WPF project and name it as PrimsModulityWithWPF.
2. Delete the MainPage.xaml file from the project.
3. Add following references from Prism desktop folder (...\PRISM4.1\Bin\Desktop).

  • Microsoft.Practices.Prism.dll
  • Microsoft.Practices.Prism.MefExtensions.dll
  • Microsoft.Practices.ServiceLocation.dll
  • Microsoft.Practices.Prism.Interactivity.dll
4. Also add new reference called System.CompenentModel.Composition.dll from  Framework Assemblies.















5. Now add new WPF Widdow to the project named as Shell.
6. Now your new project structure will be as bellow.



6. Now add new C# class and named it as Bootstrapper
7.Add new two class Libraries to your project and named them as EmployeeModule and .ProductModule and delete Class1.cs file from both project.
8.For both newly added class libraries add the following references.

  • Microsoft.Practices.Prism.dll  (  from Prism desktop folder)
  • Microsoft.Practices.Prism.MefExtensions.dll (  from Prism desktop folder)
  • Microsoft.Practices.ServiceLocation.dll (  from Prism desktop folder)
  • Microsoft.Practices.Prism.Interactivity.dll (  from Prism desktop folder)
  • System.CompenentModel.Composition.dll (From Framework Assemblies.)
  • System.Xaml (From Framework Assemblies.)
9. Add another class Library to the solution and named it as Repository.Add the Following above references to it except the System.Xaml .
10. Add new class called EmployeeModule.cs to EmployeeModule and implement this class as below.


To import module to our main application we need to create our module exportable. So we need to implement our module class as above. Module as should implement using IModule interface which has only one method called Initialize. This method used the Initialize your module before the loading. For example you can specify the view  to navigate during the initial loading of your module. We will discuss more about this soon.

Using ModuleExport attribute ([ModuleExport(typeof(ProductModule))]) We make this module as exportable.

11.Now we want to implement the module class for EmployeeModule and Repository module.First write click on EmployeeModule and add new class called EmployeeModule.cs and implement it as below.

Now right click on Repository class library and add new class called RepositoryModule and Implement it as below.



12. Now again we will move to out main project (PrimsModulityWithWPF) and we will implement the our Bootstrapper class and Shell.

Responsibility of Boostrapper : 

A Bootstrapper is the one who has responsibility to initialization of your application which is implemented using prism library.
Also you want to need that PRISM provide two dependency container libraries called MEF and Unity. For MEF container PRISM has already implemented Bootstrapper class called MefBootstrapper. Also for Unity container PRISM as already implemented bootstrapper class called UnityBootstrapper.

In our example we use dependency injection container as MEF. So we need to implement  our boostrapper class derive from MefBootstrapper.

Before jump into bootstrapper implementation  right click on References of PrimsModulityWithWPF project and add the EmployeeModule,ProductModule and Repository as solution references.

Now implement our Boostrapper class as below.

Here we have to override some of virtual methods in which are in MefBootstrapper class


  • CreateShell
The CreateShell method allows a developer to specify the top-level Window for Prism application.Shell is usually the MainWindow of your application. (Ref : PRISM 4.1 Documentation)
  • InitializeShell
After you create a shell, you may need to run initialization steps to ensure that the shell is ready to be displayed. Depending on whether you are writing a WPF or Silverlight application, the InitializeShell method implementations will vary.
For WPF applications, you will create the shell application object and set it as the application's main window, as shown here (from the Modularity QuickStarts for WPF).
protected override void InitializeShell()
{
    Application.Current.MainWindow = Shell;
    Application.Current.MainWindow.Show();
}
 (Ref : PRISM 4.1 Documentation)
  • ConfigureAggregateCatalog
This method allows you to add type registration to the AggregateCatalog imperatively.For example, the our Bootstrapper registers the current assembly,EmployeeModule,ProductModule and Repository. In other word we should register the all the module that we use in our application inside this method.Without registering we can not use these libraries inside our application. Also you can register the Module using App.config file if you are using WPF.

13. We have completed implementation of our Bootstrapper class now. So now we will implement our shell view as bellow.



Also we need to create this shell view as exportable. To do that go to Shell.xaml.cs file and add the [Export] attribute as bellow.



14. Now we can  run and test our application working as expected or not. Before that we need to perform two extra steps more. For all the modules (Except our main module) , Properties of prism libraries "Copy Local" attribute should be set as "False". Other wise our application throw an assembly conflict exception.

Right click on  Microsoft.Practices.Prism which is in EmployeeModule class library and select the Properties  and set "Copy Local" attribute as false.

 Follow these step for all other Prism libraries (Microsoft.Practices.Prism.MefExtensions, Microsoft.Practices.ServiceLocation,Microsoft.Practices.Prism.Interactivity). And do the same steps for all other class libraries (EmployeeModule,Repository).

Now open you App.xaml file and delete StartupUri part from it. After that your App.xaml file should be like this.

Now go to the App.xaml.cs class and override OnStartup method as bellow.

Now rebuild your application and run it. if you complete above steps correctly you can see the empty shell like below.


15. we can implement our modules one by one. First we will implement the out Repository module which contain the all the business logic.

First we will implement the our model class for Employee and Product. Right click on  Repository module and create new folder called Model.

Create new class called "Employee" and implement it as bellow.



Create new class called "Product" and implement it as bellow.


Now we will implement the Interfaces for EmployeeRepository class and ProductRepository class. Right click on Repository module and create new folder called Repository and then right click on Repository folder and create new folder called Interfaces. Now create two interfaces named by IEmployeeRepository and IProducRepository and implement interface method definition as bellow.

IEmployeeRepository



IProductRepository


Now right click on the Repository folder and create new class called EmployeeRepository and implement the class using IEmployeeRepository interface as below.


Here you can  see [Export] attribute and it enable the Exportability of the EmployeeRepository (Since we use type as IEmployeeRepository  interface and since our class derived from same interface it enable exportability for EmployeeRepository class).

Now again right click on the Repository folder and create new class call ProductRepository and implement the class definition as below.


Our repository module implementation has completed now.

16. Now we will implement out EmployeeModule. Here what we going to do is, we call the GetAllEMployee methods which is in Repository module  and get the employee list and we will display the employee list in Shell's "EmployeeRegion"

Also I assume that  you have experience with MVVM design pattern and also XAML data binding.

First select the EmployeeModule class library.Right click on References and add Repository project as solution reference.

After that create two folders called View and ViewModel inside EmployeeModule class library.

Right click on the ViewModel class and create new class called EmployeeViewModel and implement the class as below.



You can see that EmployeeViewModel exportable because of [Export] attribute. Also look at the constructor and there we have use the [ImportingConstructor] attribute.By using this we can import the parameters to the constructor. Here we import the IEmployeeRepository interface here. (If you look at the EmployeeRepository class you can see that it is Exportable. So we can import it from our EmployeeViewModel constructor.). Also You can see that in constructor we used dependency injection here.It helps us to build loosely couple testable application.

Now right click on View folder and create new WPF usercontrol. Implement the view as below.


Now open the EmployeeView.xmal.cs  and implement the class as below.


 Now open the EmployeeModule class and  add extra line of code as below.



Here we import the IRegionManager iterface using [Import] attribute and we use the import object to Navigation. (or View loading).

When EmployeeModule loading it first call the Initialize method. Inside method we  load our ProductView into ProductRegion which is in Shell. For that we call the RequestNavigate method.

17. Now we will implement our ProductModule.. First select the ProductModule class library.Right click on References and add Repository project as solution reference.

Then create two folder called View and ViewModel on ProductModule class library.

Right click on the ViewModel folder and create new class called ProductViewModel. Implement the class as below.


Now right click on the View folder and create new WPF usercontrol called ProductView. Implement it as below.


Now go to ProductView.xmal.cs and modified the class as below.



Now open the ProductModule.cs and modified the class as below.


Now we have completed our development.So rebuilt and run your application. If you are following steps correctly you will see the following window.



Happy Coding!!!!!!!!!!!!!!!!!!