June 2011

Volume 26 Number 06

Multi-Targeting - Build Multi-Targeted Apps for the Desktop, Prism and Windows Phone 7

By Bill Kratochvil | June 2011

Microsoft provides powerful frameworks for developing scalable, extensible applications. Some recent projects—Prism, the Managed Extensibility Framework (MEF) and Unity—provide multi-targeting capabilities. Multi-targeting permits you to have a single code base that can be shared across the desktop, Silverlight and Windows Phone 7 platforms. These free tools have comprehensive documentation with quick starts, labs and plenty of sample code to help get you started. To maximize your return on investment (ROI)—man hours spent researching and learning—it’s important to understand that you must approach these tools and documentation with a new way of thinking.

Prism, the MEF and Unity use advanced patterns of software development that can make the learning curve difficult for most of us developers—so difficult that it may appear to lack an ROI. They require you to not only have a new way of thinking, but to have an understanding of the tools and the patterns involved. Failure in either area will be costly in terms of the learning curve and application stability. Fortunately, if you have a few basic concepts under your belt, you’ll not only understand the tools and documentation, you’ll be able to open any Prism, MEF or Unity application and quickly navigate through it so you can learn or reuse the best of what’s available to create your multi-targeted applications. These concepts include the project linker, dependency injection (DI), sharing code and architectural patterns.

The Project Linker

It’s important to understand that projects can’t be shared between platforms. Desktop projects can’t reference Silverlight projects and Silverlight projects can’t reference desktop projects. Likewise, a Windows Phone 7 project can’t reference Silverlight or desktop projects. You aren’t sharing projects, you’re sharing code. This requires you to create a project for each platform and “link” the files.

Linked files in Visual Studio are identified with a shortcut symbol on the file icon and do not physically exist on your hard drive.

Note in Figure 1 that only the Phone (source) project has code; the Desktop and Silverlight target projects have linked files, so their folders are empty.

Only Source Projects Have Code

Figure 1 Only Source Projects Have Code

The Prism project (compositewpf.codeplex.com) includes a project linker application; without this tool, the management of multi-targeted applications would quickly become a daunting task. It allows you to establish a source project and link to target projects so that any action you perform on the source—for example, add, rename and delete folders and files—will be duplicated in the target projects.  

Naming conventions become increasingly important in multi-targeted applications. The linked projects should all share the same name with the exception of a suffix, which represents the platform. For folder structure purposes, it’s best to create the project with the suffix—for example, Gwn.Infrastucture.Desktop—and then remove the suffix from the default namespace from the project configuration, as shown in Figure 2.

Remove the Suffix from the Default Namespace After Creating the Project

Figure 2 Remove the Suffix from the Default Namespace After Creating the Project

This ensures that your folder structures won’t be ambiguous or cause you problems when creating new projects (with the same name) for the other platforms. Removing the suffix from the default namespace is an important step; because we’re sharing the code on multiple platforms, the code must not have platform-specific namespaces, or the other platforms will complain during compile time.

The preceding guidance also helps you maintain your sanity during development. If you inadvertently add an assembly reference to a different platform—for example, in Figure 2 my Desktop application has a reference to a Silverlight assembly—you’ll get a confusing error message (because it does exist in the namespace). A quick glance at the project references will reveal the culprit if you used a platform suffix.

Microsoft provides excellent documentation for the project linker at msdn.microsoft.com/library/dd458870. In addition, you can use the Bing search engine to search for “project linker” and find other valuable resources, including a link from myself (aka BillKrat), which has a webcast that walks you through the project linking process. (Note: The installation process is far easier than noted in documentation if you’re using Visual Studio 2010. From the menu options, you can go to Tools | Extension Manager, search for “Project Linker” and then install it from there.)

Dependency Injection

To understand Prism, the MEF and Unity, you’ll require an understanding of DI. Without it, the documentation and samples will seem foreign to you and your learning curve will be harder than it has to be. We’ll limit the topic of DI to the Unity container (unity.codeplex.com); once you understand DI, you’ll better grasp the MEF (mef.codeplex.com) as well.

What’s a DI Container? At a high level you can look at a DI container as an over-glorified dictionary class that has the power to create classes. In this dictionary, you can register interfaces and their implementation (or instances)—dictionary.add(IFoo,Foo), for example. When you tell your container to create IFoo—an interface—it will search the dictionary, find it has a type (Foo) and instantiate it. After instantiating Foo, it will see if Foo has any interfaces that need to be resolved, and the chain continues recursively until all children have been successfully created. Once completed, the container returns an instance of Foo.

Constructor and Setter Injection Typically, code statements will instantiate a class so that it can use its resources (Figure 3, line 18).

Constructor and Setter Injection

Figure 3 Constructor and Setter Injection

With DI, the classes are resolved (instantiated) externally and instances are injected into the class by the DI container. Unity supports two types of injection: constructor injection and setter injection. With constructor injection (Figure 3, line 25) the container will dynamically create the MyTaskConstructorInjection class, resolve IFoo and pass it in as a constructor parameter. After the Unity container constructs the class and injects parameters, it will search the class for dependency attributes (Figure 3, line 33) and resolve the properties. Because setter injection doesn’t occur until after constructor injection, you can’t reference properties with the dependency attribute in your constructor.

Registering Types In order for the container to resolve interface types, such as IFoo, the implementation must first be registered with the container (see Figure 4, lines 49 and 50).

Registering the Implementation with the Container

Figure 4 Registering the Implementation with the Container

Generally the registration will be made in the application’s bootstrapper, module or presenter/controller because these are typically the initialization classes. Once interfaces are registered, the container will know how to resolve an interface when it’s encountered in the dependency chain.

Extensible, Scalable Applications For the sake of discussion, let’s say that the Foo class is a data access layer (DAL) that your enterprise uses to access your SQL Server database. It’s used by hundreds of modules and numerous applications. Management just completed a licensing agreement with Microsoft—for cloud services—and you’re notified that you’ll have to upgrade your applications to utilize the cloud. During the migration, Foo will continue to be used by some applications (for the SQL Server database), while the others will be moved to the cloud. For those applications migrating to the cloud, you need to be able to switch back to the old database quickly in case the data migration failed for any reason. How long would this take you?

Using DI, it will only take a few lines of code! The pseudocode follows:

var  isCloud =  GetCloudConfigurationFromConfigFile();
if(isCloud)
  container.RegisterType<IFoo, FooCloud>();
else
  container.RegisterType<IFoo, Foo>();

Because your enterprise applications have integration testing, you can perform test-driven development (TDD) on the new FooCloud DAL. Once TDD is completed, you’re ready to update each application’s bootstrapper with the preceding code and deploy it with “NO” regression testing required for the applications that continue to use the SQL Server database (Foo class), because the code hasn’t changed.

The following business logic layer (BLL) could potentially be used by hundreds of presenters/controllers. Because it deals strictly with domain objects, we won’t have to touch this code—or any code that consumes this BLL—because we code against a DAL interface (IFoo):

public class FinancialDataBll  : IFinancialDataBll
   {
     [Dependency]
       public  IFoo Dal {get;set;}

       public  IEnumerable<FinancialEntity> 
         GetFinanicalData(object sender, EventArgs e)
       {
         // Validate event arguments prior to calling data layer
         var returnResults = Dal.GetFinancialData(sender,e);
         // Handle errors with friendly messages as applicable
         return returnResults;
       }
   }

Had you tightly coupled your code to the Foo class in Figure 3, line 18, then your applications wouldn’t be as extensible and the migration process would be considerably more costly in terms of coding and testing.

Layers Effective utilization of DI requires that you properly structure your BLLs and DALs. The BLL should have no knowledge of the DAL components—for example, connection strings, SQL statements, file handles as XML files and so on. Likewise, your presentation layer (UI components) should have no knowledge of the DAL; it only knows of the BLL. (Note: Your BLLs could be swapped out just as easily as the DAL if your presentation layer uses DI to resolve its BLLs; this is invaluable if you have to perform a refactor but only want to affect one application.)

Event Aggregation Communication between decoupled components can introduce challenges. In the example shown in Figure 5, object D contains a drop-down list the user will use to change the currency type—for example, United States dollar to euro. 

Communication Between Decoupled Objects

Figure 5 Communication Between Decoupled Objects

The objects B and F are biased by the currently selected currency and have to be recalculated when the currency is changed. One possible solution would be to bubble the event to A (where A subscribes to B, B subscribes to C, and C subscribes to D) and then tunnel the information from A to E, which in turn would tunnel it to F. As the application grows, this process gets more complicated. This complexity would extend to testing, as all affected areas would have to be regression-tested if conditional statements were added anywhere in the path.

To prevent memory leaks for this solution, we would have to ensure we implemented IDisposable on all affected objects and disposed all event subscriptions; this adds another layer of complexity that would have to be managed.

Prism Event aggregation is one of the many areas in which Prism shines. With Prism, you can simply publish an event in D using a syntax comparable to the following:

aggregator.GetEvent<MyEvent>().Publish(MyPayload)...

Objects B and F would subscribe to this event, so after writing just a few lines of code, you’d be focusing on business logic and wouldn’t have to be bogged down in infrastructure plumbing. An example subscription from B and F is shown here:

[Dependency]
public ILoggerFacade Logger {get;set;}

private  IEventAggregator _eventAggregator;
[Dependency]
public  IEventAggregator EventAggregator 
{
  get { return _eventAggregator; }
  set { 
    _eventAggregator=value;
    OnEventAggregatorSet();  // Subscribe to events in this method
  }
}

And here’s another example:

public  MyConstructor(IEventAggregator aggregator){
  aggregator.GetEvent<MyEvent>().Subscribe(HandleMyEvent);  
}
public void HandleMyEvent(MyEventArgs e){
  Logger.Log("HandleMyEvent is handling event in Foo", Category.Debug, Priority.None);
 // Do something useful
}

Sharing Code and XAML

Before Electronic Health Record (EHR) certification requirements were established (making EHR development cost-prohibitive for small offices), I wrote an EHR application for a small medical group. It started with a Windows Mobile PDA and Web site for the purpose of accurately managing patient care and billing. The PDA had all the business logic, and the Web site provided an interface for the billing staff. Slowly, features of the PDA were migrated to the Web site and the expectation was that all of the business rules and behaviors would be migrated, too. To complicate matters, I was later asked to create a desktop application for their tablets and laptops, and, within a year, the scope of the project changed from a PDA to all three platforms. I found myself having to manage three separate code bases; each had platform-specific variations, which didn’t make sharing business logic straightforward.

When the project linker emerged in the Prism project, and the patterns & practices design team shifted gears to support a multi-targeted environment (using the same namespaces across platforms), I was immediately on board because I fully appreciated the ramifications of the direction they were taking. Using multi-targeting, the EHR project could be done in a fraction of the time and at minimal cost to my client for development, upgrades and maintenance.

Code Much thought has to go into the platforms you’re going to support. It’s important that your single codebase be in the least-supported platform. For example, if you’re only going to program in the Silverlight and desktop environments, then you’ll set your Silverlight projects as the source and the desktop projects will link to them. If you’re going to support Windows Phone 7, Silverlight and the desktop, then the Windows Phone 7 projects need to be the source.

This is important because you don’t want to waste your time writing code that won’t compile on the other platforms. If, for example, you develop on the Windows Phone 7 platform, you’ll quickly see, via IntelliSense, what framework features are available. You can write your code with confidence that it will compile on the other platforms.

It’s also recommended that you set a standard for your project’s “Conditional compiler symbols” configuration (see Figure 6; note that highlighted areas show default settings).

Set Compiler Symbols for Each Platform

Figure 6 Set Compiler Symbols for Each Platform

I found this to be an issue because “SILVERLIGHT” is shared in both the Windows Phone 7 and Silverlight projects; to code specifically for Silverlight 4, I had to do the following:

#if SILVERLIGHT
#if !WINDOWS_PHONE
  // My Silverlight 4-specific code here 
#endif
#endif

XAML XAML was surprisingly easy to reuse, particularly between Silverlight and desktop applications; the trick is to not have any assembly references in your XAML. I accomplished this by creating a wrapper class (see Figure 7, top-left panel) within the local project that subclasses the actual class in the external assembly.

Create a Wrapper Class for the Current Project

Figure 7 Create a Wrapper Class for the Current Project

Notice that my UserControlBase class programmatically loads the platform-specific resource file, which contains the converters, styles and templates that allow me to have minimal XAML declarations that might affect my ability to share it.

Architecture Patterns

If you put 10 programmers in a room and assigned them the same development task, it’s likely that you would see 10 different ways to successfully complete it. As developers, we have varying levels of architectural and coding experience that could easily be reflected in the code we write (making our enterprise applications hard to follow and maintain). Architectural patterns and standards provide us a common core of experience, which would have the 10 developers coming out of the room with comparable code.

Windows Presentation Foundation (WPF), Prism, the MEF and Unity introduce a development environment unlike any other. The addition of multi-targeting throws in an added level of complexity—particularly if you use it effectively, minimizing platform-specific code. With evolving technology in an agile world, patterns need to be constantly updated to effectively leverage the new technology being offered; it’s inevitable that you’ll see a multitude and combination of patterns as you review the samples these powerful tools provide.

If you don’t recognize patterns, you’ll have difficulty understanding the tools, documentation and samples; worse yet, you can use these powerful tools in a way that violates their intended design, which will become a risk to the success of your project. Appendix B in the Prism documentation provides comprehensive information on applicable patterns. I’ll summarize the evolution of presentation patterns in the next section.

Model-View-Controller (MVC) Application Model This model emerged as the solution to issues encountered with MVC, more specifically the pollution of domain objects with business logic and UI state, such as text color, a selected item in a list, visibility of the control and so on. It also provided the ability to update the view directly (something not permitted in MVC).

The Application Model was inserted between the View and the Model and contained business logic to manage behavior, state and synchronization with the Model. The View would bind to the Application Model (versus the Model).

MVC Presentation Model The main distinction between the Presentation Model and Application Model lies in its ability to update the View. Presentation Model follows MVC guidelines and doesn’t permit the updating of the View directly.

Model-View-ViewModel (MVVM) John Gossman, MVVM creator, states the following:

“On naming, my opinion at this point is the [MVVM] pattern is a WPF-specific version of the Presentation Model pattern. Presentation Model is a lot easier to say and to write, and is more widely known ... but for now, I’m sticking to MVVM terminology in my own thinking in order to capture the WPF-ness and to avoid any interpretation conflicts.”

Model-View-Presenter (MVP) MVP was the solution to the limitations of the MVC, Application Model and Presentation Model patterns. With MVP the developer is empowered to control the View and ViewModel. Windows developers have always had the luxury of smart controls to work with, so the distinction between MVC and MVP may not be clear to many of us. With a little research, you’ll find that Windows made the MVC controller obsolete because the OS and controls included most of the controller functionality.

The need to evolve from MVC wasn’t limited to the obsolete controller; other factors were limitations in the Application Model and Presentation Model as already discussed.

Here’s an outline of the components of MVP:

Model The Model contains the data the View will be bound to.

View The View displays the contents of the Model through data binding. This separation is important because a View can be shared by multiple Presenters. (Note: In 2006, Martin Fowler split the MVP pattern into two distinctly different patterns: Supervising Controller and Passive View. The main difference between the two is centered on data binding; if data binding is used, then it’s referred to as Supervising Controller [following the responsibilities previously outlined]. If there’s no data binding, it’s referred to as Passive View and the responsibilities shift; it becomes solely the Presenter’s responsibility to keep the View synchronized with Model.)

Presenter The Presenter has knowledge of both the View and the Model, with the responsibility of handling business logic and populating the Model.

Model-View-Presenter, ViewModel (MVPVM) This (unnamed) pattern was found in an early drop of the Prism project; it combined the power of MVP and MVVM:

// Load the view into the MainRegion 
  // after the presenter resolves it
  RegionViewRegistry.RegisterViewWithRegion("MainRegion", () => 
    presenter.View);

This simple line of code, coupled with lessons learned from the patterns & practices team while using their Prism, Unity, Smart Client Software Factory (SCSF) and Web Client Software Factory (WCSF) projects, would be used to create the pattern that I appropriately call MVPVM. With this pattern, the Presenter is responsible for resolving (instantiating) the ViewModel, View and required BLL components. The Presenter then makes the necessary calls to the applicable BLL methods (see Figure 8) to populate the ViewModel with data for the View to display.

Model-View-Presenter, ViewModel  (MVPVM) and Associated Components

Figure 8 Model-View-Presenter, ViewModel  (MVPVM) and Associated Components

Because the business logic resides in the Presenter, the ViewModel can be easily reused by other Presenters. In addition, the Presenter can update the View directly to eliminate complex binding logic (if applicable), particularly when a control reference is required. As such, MVPVM resolves (no pun intended) all of the limitations of Application Model, Presentation Model and MVVM (as outlined by our renowned architects) for our multi-targeted Prism and DI environment.

You’ll find the preceding line of code in the SecurityModel of our Password Manager open source project at PasswordMgr.CodePlex.com. This multi-targeting project has desktop, Silverlight and Windows Phone 7 applications sharing a single codebase, with the Silverlight and desktop applications sharing the same XAML.

(Note: As of this writing, there’s no official support for a DI container on the Windows Phone 7 platform. For this project, I downloaded the ContainerModel from the Windows Mobile 6.5 project [mobile.codeplex.com], implemented the IUnityContainer interface [from the Unity project atunity.codeplex.com], pulled over a number of the Unity unit tests and performed TDD until all unit tests passed. With the newly constructed DI container, which looks and feels like Unity, I was able to port over the Prism project—this Password Manager project has more than 800 unit tests and compiles with zero errors, warnings and messages.)

Model The DAL will have sole responsibility for persisted Model objects. In addition, it has the responsibility of transferring the persisted Model objects to the domain objects (entities that represent the model that are within the scope of all enterprise application layers). (Note: The BLL has no knowledge of the presentation layer or the Model; it only communicates to the DAL through an interface.)

View The View observes the ViewModel (data binding) and displays the data on the ViewModel as applicable. A View only has one ViewModel; however, the ViewModel can be shared by multiple Views.

Presenter The Presenter is responsible for instantiating the View and ViewModel, setting the View’s data context, wiring up events and handling business logic for any events and behaviors (mouse and button clicks, menu selections and so on).

The Presenter will use (shared) BLLs to handle business logic and perform create, read, update and delete (CRUD) operations on persisted model data. (Note: BLLs are easy to unit test and can be easily replaced using DI.)

The Presenter shares the MVP ability to directly modify the View, its controls and the ViewModel.

ViewModel The ViewModel can be reused by numerous Views, so it should always be designed with sharing in mind.

The ViewModel can communicate with the Presenter using either event aggregation (preferred) or through interfaces (for generic functionality). Typically this will be handled by a ViewModel base class (communicating with a Presenter base class). This communication is required because the Presenter handles all business logic, but the View will have its commands and events bound to the ViewModel; these events need to be propagated to the Presenter in a loosely coupled manner for processing.

Power and Versatility

With these basics under your belt, the segment of code shown in Figure 9 shouldn’t appear so foreign to you now.

Module Registrations

Figure 9 Module Registrations

The power and versatility of the tools the patterns & practices team provides should be apparent, revealing a significant ROI. They abstract the complexity of the infrastructure from you, allowing you to create loosely coupled, scalable and extensible applications—applications that can share the same codebase so that you can accomplish more work with fewer resources in a reliable and stable manner.

Effective utilization of layers (presentation layers, BLLs and DALs) provides a clear separation of concerns, enabling you to reuse your components across multiple modules and applications. This minimizes costs for testing, new development, upgrades and maintenance.

Most importantly, you can create high-velocity, agile teams that can slide through a world of constant change by leveraging their experience and domain knowledge so they can focus their talent on business logic (not infrastructure) in a single codebase, permitting them to construct applications that will work on the Windows Phone 7, Web, tablet or desktop platforms.


Bill Kratochvil, an independent contractor, is a lead technologist and architect for an elite team of developers working on a confidential project for a leading company in the medical industry. His own company, Global Webnet LLC, is based in Amarillo, Texas.

Thanks to the following technical experts for reviewing this article: Christina Helton and David Kean