posted by: Ralf Rottmann | posted @ Wednesday, July 02, 2008 9:21 AM | View blog reactions

One of my dev teams over at VoicInt Telecommunications currently works on a Windows Presentation Foundation based product that facilitates a rich add-in infrastructure. A key feature area of the soon-to-be-shipped release is a completely modular architecture which not only allows to parallelize much of the engineering process but also gives our VARs and resellers the ability to extend our product to individual customers' needs.

With the beginning of the year we've adopted a strict agile development approach and since then successfully follow the Scrum methodology. In a series of exploration sprints we've focused on prototyping around the idea of a true Composite Windows Presentation Foundation application.

Some of the high-level requirements we wanted to address were:

  • Load and unload of discrete modules (= assemblies) at runtime
  • Loose coupling of all modules
  • Communication between modules based on loosely coupled services
  • Thread isolation
  • Exposure of a UI shell which hosts merely autonomous UI panels

One of the great things in our industry is that one always never has to start entirely from scratch. In fact it turned out that creating an extendable application is a quite common scenario with many great ideas and code projects out there, although there are less resources as of today specifically addressing the concerns of WPF based solutions.

Composite Application Guidance for WPF (Prism)

An excellent entry point has actually been published by Microsoft's patterns & practices group on their Composite Application Guidance for WPF site. The scenario was first addressed by the Composite UI Application Block (CAB) and the Smart Client Software Factory and has been extended to the emerging WPF world with the Prism project. To avoid naming confusion here: The project has long been known as Prism but nearing the RC 1 release has been renamed to what's now Composite Application Guidance for WPF. Because I like the shorter version better, I'll continue to refer to it as Prism.

Prism's dynamic composition capabilities addressed some of the main technical challenges we were facing. Specifically:

In UI Composition it provides

  • UI consistency
  • Layout
  • UI workflow
  • Separating the UI from business logic
  • Allows integrating graphics designers later in the process
  • Communication between different UI components

Concerning the required Modularity

  • It promotes separation of concerns through allowing a high degree of separation between the application infrastructure and the business logic.
  • It allows different teams to independently develop each of the individual business logic and infrastructure components.
  • It allows parts of the application to separately evolve.
  • It promotes code re-use and flexibility because it allows business logic components and the application infrastructure to be incorporated into multiple solutions.

Prism introduces a couple of new technical concepts.

A Module in Prism is a logical unit within an application. Modules assist in implementing a modular design. These modules are defined in such a way that they can be discovered and loaded by the application at run time. Because modules are self-contained, they promote separation of concerns. Modules can communicate with other modules and access services through various means. They reduce the friction of maintaining, adding, and removing system functionality. Modules also aid in testing and deployment.

Commands are a way to handle UI actions. They are a loosely-coupled way to bind the UI to the logic that performs the action.

When building composite applications, presentation design patterns such as MVP and MVC are often used to separate the UI logic from the UI layout and presentation. When implementing these patterns with WPF, the presenter or controller handles commands, but lives outside the logical tree. WPF routed commands deliver command messages via UI elements in the tree, but the elements outside the tree will not receive these messages because they only bubble up or down from the focused element or an explicitly stated target element. Additionally, the WPF routed commands require a command handler in the code behind.

Prism introduces several new commands that can be routed outside the boundaries of the logical tree and that do not require handling logic in the code behind. Prism commands are custom implementations of the ICommand interface defined by WPF, and implement their own routing mechanism to get the command messages delivered to objects outside of the logical tree.

To keep everything loosely coupled Prism incorporates the Dependency Injection pattern everywhere and anywhere. The reference implementation makes use of Microsoft's own lightweight extensible dependency injection container, Unity. Prism is designed to support other dependency injection containers, too, but we have not yet tried to refactor this part of Prism.

While Prism has been an excellent starting point for us we are currently evaluating to implement our own solution from scratch - taking into account many of the great ideas and maybe even some code of the Prism implementations. There are a couple of reasons for this:

Prism's Region Manager

Prism ships with a region manager which effectively handles the loading of discrete WPF components into shell layout regions at runtime. The application we are designing implements a sidebar user interface and requires very rich and interactive docking and magnetic (similar to what you might know from Winamp) behavior. The screen shot of our current prototype below illustrates some of the concepts:

image

Our sidebar facilitates regions which can be

  • resized,
  • rearranged,
  • dragged out of the sidebar,
  • docked into the sidebar,
  • docked together and moved as a group,
  • minimized and maximized and
  • shown/hidden.

The current region manager in Prism has not been designed for all of these of use cases. We are currently looking into replacing it with our own implementation.

Module Loader

We experienced some shortcomings in the Module Loader. As an example we found it difficult to access a list of successfully loaded modules at runtime (which we would require to offer a traditional View > Windows menu). Chances are this can be done, however, we found it extraordinarily complicated for such a common task. This lead to overall concerns regarding the thorough design with respect to extendibility and openness of the Prism application block itself.

Prism's DI Container

As stated above Prism makes use of Microsoft's Unity IoC Container. In general we do like Unity and ObjectBuilder2, which it builds upon. However, they might be a bit too heavyweight for what we are looking for. So one other aspect of our evaluation is looking into Castle Windsor, StructureMap and others. We lately added Ninject to our list and from a first look at the documentation, we like it's overall agile implementation.

No solution for isolation

Prism does not offer anything related to the problem of isolating code which gets loaded at runtime. This is a pretty serious issue. Many .NET developers instinctively respond with the magic of AppDomains when it comes to isolation. Unfortunately, however, AppDomains do not at all address isolation issues. In fact they only help you with loading and unloading assemblies at runtime. In case code residing in a module raises unhandled exceptions your main application (the host) will fail, too. There's an interesting discussion here and probably some answers here. As of now it seems as if the only real secure way to tackle the problem of isolation would be to run each module in its own process. (Interestingly the Internet Explorer team at Microsoft introduced some significant changes to how IE 8 handles isolation which seem to stem from the same root cause.) As isolation is of major importance to us we are currently looking into which options would be feasible in terms of the effort/benefit relationship. Stay tuned for more on this!

Preliminary conclusion

Prism has helped us getting started a lot. In general the folks at Microsoft patterns & practices are a great resource and always willing to help and assist. With the lack of support for isolation, the requirement of our own region manager and the pretty heavyweight dependency injection container we have not yet made the final decision to actually use Prism.

We are planning to come to a conclusion within the next two weeks. I'm going to publish a follow up post on our further findings.

comments
Glenn Block stated:
# re: add-in and plug-in apps with .net
Ralf, we should chat about your issues. We'd like to understand your specific region manager issues, and also around the module loading. You should be able to get the list of modules that are loaded (at least initially) through the module enumerator service.

If not, replacing the services is quite easy.

Glenn
posted on 7/4/2008 7:31 AM
post your comment
Title *
Name *
Email
Url
Comment *  
Please add 4 and 7 and type the answer here: