I am currently digging deep into Composite WPF applications for our side project which I am working along with a friend of mine. For anyone who wish to get started with Composite WPF application design and development, I recommend you first watch the screen-cast by Jason Dolinger on WPF Model-View-ViewModel and then go ahead to watch the DnrTV show on Prism by Brian Noyes.
With information from both the videos, I made a lot of notes on paper but I am having trouble implementing the same ideas to an application of mine. Anyway I hope to resolve this issue with time and I just need a quick start. In that process, I have looked at some slides by Noyes from a talk on Prism. The following is my observations (which might be incorrect) and notes on CompositeWPF and as well as on Model-View-ViewModel pattern in WPF.
A composite WPF application has the following parts
- Container – PRISM uses Unity Container by default. But it allows the developer to use any container of their choice. The Container is used to perform dependency injection (inversion-of-control). My understanding of dependency injection is – Project X would not refer to Project Y and yet be able to load Y at runtime. This makes both X and Y as loosely coupled as possible. By inversion-of-control, we mean that the control of generation of objects and dependent objects is moved from the host object to the container.
- Bootstrapper – Bootstrapper is a class (derives from UnityBootstrapper in CompositeWPF) that is used to manage the startup of the Shell program or the main window. The Bootstrapper also performs configurations as required – configuration of the container, configure the regions mapping using regions-mapping-adapter, creates the shell, initializes the modules. An instance of BootStrapper is created and Run() is called from the Initialize() method of the App.xaml. When bootstrapper is used, we remove the StartupUri from the App.xaml. The bootstrapper is not a required component but is recommended. I usually go with any thing that is recommended.
- Shell – A Shell is a WPF Window – the main Window. This is the window that would be instantiated and shown from the Bootstrapper class. Shell knows nothing about the modules and is just the UI Container for the application (the root UI element).
- Modules – A module is an independent and loosely coupled unit of the composite application. It might be a GUI module with WPF Views inside the module or might just be a service module which provides the required services used by the application. One major addition that PRISM brings to WPF with CompositeWPF is the ability to load modules as and when required instead of referencing to the modules. This makes the application to be capable of extensions (like the Eclipse – the most popular extensible application). Some of the module loaders are StaticModuleLoader, DirectoryModuleLoader, etc.
- Views – Views reside in module. View is the visual aspect of the application. When we talk about views, i think it would be a good time to talk slightly about MV-VM pattern. In the MV-VM pattern, the code-behind or the View is kept very clean. Not much code would be written and the view goes through the ViewModel to interact with the Model. Model would have no idea about the View and View only deals with the ViewModel. View updates the model from the ViewModel using Two-way databinding, an excellent feature of WPF. In Jason’s talk, he actually mentions that a clean MV-VM implementation is one in whose View, the controls would not be required to have x:Name specified. I like this litmus test in particular since it is the most easiest way to ensure the MV-VM being followed. Composite View is a view that is composed other views and it is responsible for composing itself of the the child views. It might have content of its own.
- Services – Model are the data objects which are displayed/modified via the Views. But these objects are to be created using a service. For example, InternetQuoteService generates Quote objects to give to the QuoteManager application. Services also sit in the modules and typically follow the singleton instance model.
So why do we need to use CompositeWPF (CAL or PRISM or shit)?
Look at the baseline architecture of the Composite Application Library.
If you would not use CAL, then you have the additional burden to implement all the portions that is in BLUE. And you should not forget that the design that you come up might not actually be a great design and using CAL helps you take advantage from the experience of the architects in the patterns & practices team. To summarize, the CAL provides the following services:
- Region Managers
- Event Aggregators
- Module Enumerators
- Module Loaders
The Unity API
First of all, I read this amazing article on Dependency Injection/IoC and Unity which I unfortunately lost the link to. (remember I formatted my laptop). Anyway , get a good link and understand what dependency injection is and then you need to know that the unity api has the following important methods.
- Register – tell the container that it is responsible for creating this object.
- Resolve – fetch an object from container which was Register-ed.
- BuildUp – inject dependencies into the existing object
- Configure – Register based on the configuration information.
I would be writing more on my experiences and I feel I have invested a lot of time, just trying to understand the LOB aspect of WPF applications. I know how the UI should look in our application but want to do it the correct way from the beginning. Hopefully, I would have the basic structure for the application ready, as soon as possible.
If you are into CompositeWPF and are looking for someone to discuss ideas or for any other general discussion, you can reach me at email@example.com