February 11, 2010 12:00 AM

Introduction to Using Prism with Silverlight 3

Break your monolithic applications into manageable chunks
Dev Pro
InstantDoc ID #124942
Downloads
124942Code.zip

Microsoft's patterns and practices group designed Prism, formally known as the Composite Application Guidance for WPF and Silverlight, to help you build modular Windows Presentation Foundation (WPF) and Silverlight client applications more easily.

Prism offers several key benefits. It promotes modularity through the various classes and services it provides in the Composite Application Library (CAL). It gives the ability to compose the overall UI using independent views. It offers extensibility through the various interfaces and base classes provided, and it lets you adopt as little or as much of it as you need in your application without having to include the entire CAL. Prism's chief goal is to offer guidance for building composite applications. You can download it from Microsoft.

Composite Applications
If you've ever worked on an application that was hard to extend, maintain, test, and deploy, and was so tightly coupled that correcting one defect introduced several new ones, you know all too well the horrors of a monolithic application. Sadly, most applications in the wild suffer from exactly this malady. It's so prevalent that you may wonder if there's an alternative to deliver you from this nightmare. This is where the idea of a composite application was born.

Composite applications seek to address the evils of monolithic applications by introducing modularity and the use of shared services. In a composite application, developers create loosely coupled and independently evolvable modules that work together in the overall application. Each module in a composite application is designed to be independently created, maintained, tested, and deployed, often by separate teams. These modules communicate with one another and the main application shell using loosely coupled events and interfaces aimed at reducing the concrete references between modules.

It's important to understand that some level of dependency between modules in an application is a necessity. However, compile-time dependencies where one component directly depends on another component's type or implementation aren't. In a composite application, you seek to reduce these necessary dependencies between modules. One of the most common ways to provide this decoupling is to offload the management of these dependencies to another, intermediary object. Before I introduce this object and its important role in a Prism application, I'll need to introduce the concept of dependency injection.

Dependency Injection
In a composite application, the necessary dependencies between modules are often mitigated by the use of interfaces at compile-time and through the resolution (or injection) of the concrete references at run-time. This run-time injection of dependencies is appropriately named Dependency Injection (DI) and is a specialized version of the Inversion of Control (IoC) design pattern. (DI and IOC are described in detail on Martin Fowler's website. The task of managing and injecting these dependencies in an application that uses DI is handled by what Fowler calls an assembler object, but which is more commonly referred to as a DI container. DI containers play a large role in a composite application, so it's important to spend some time them before you start creating a composite application with Prism.

The DI container is the glue used to compose an application into a composite application. It manages and injects the concrete dependencies and provides a collection of shared services (often singletons) and creates and injects these where needed. There are a couple of standard ways that these dependencies can be injected, including constructor and setter injection.

In constructor injection, an object's constructor includes the required dependency as one of its parameters, usually as an interface, like so:

// constructor with injected dependency
public ZipEntryViewModel(IForecastService forecastService)

In the above code, the concrete type that implements IForecastService isn't known at compile time. At run time, the concrete object that implements IForecastService is injected by the DI container into the ZipEntryViewModel class's Constructor. The DI container knows which concrete class to inject based on the type previously registered with the DI container, as in

container.RegisterType<IForecastService, MyForecastService>();

This RegisterType method essentially says that any time an IForecastService is requested, it should be resolved to a concrete MyForecastService object. This lends itself well to being substituted with a mock object in unit testing scenarios, because you could replace MyForecastService with a mock object that implements IForecastService.



ARTICLE TOOLS


Comments
    There are no comments to display. Be the first one!
You must log on before posting a comment.

Are you a new visitor? Register Here