Practical .NET

Adding Business Services in WPF with Prism and Unity

WPF with Prism and Unity allow you to create loosely-coupled applications that assemble themselves at run time. Here's how Prism and Unity allow you to dynamically integrate business logic into your application.

In an earlier column, I introduced WPF+Prism+Unity, which form Microsoft's recommended technology base for creating applications that assemble themselves at run-time. This technology set is all about creating loosely-coupled modules that you can update or replace without having to recompile every other part of the application. This strategy supports application development where an application is built by more than one person working in parallel, or where the application is expected to evolve over time, requiring components of it to be replaced.

In the WPF+Prism+Unity world (or Silverlight+Prism+Unity), an application begins with the Shell, which includes the user interface (a WPF window). That window displays one or more WPF User Controls. The rest of the code for the application itself is distributed over one or more Modules. In the previous article I created a Module consisting of a WPF User Control (a View) to be used in the Shell, and a class with all of the UI logic for the View (a ViewModel). What I didn't address was incorporating any non-UI business functionality: What, in "Prism-speak", is called a service. Fortunately, incorporating business logic isn't much different from incorporating UI logic.

Defining Service Modules
The first step is to define where the application will find its modules. You do that in the Shell (the start point for the application with the WPF form that forms the UI). There are a number of ways of doing that (and I'll eventually be looking at one other method, using a configuration file), but I'll stick with defining a folder in the same folder as the application's EXE. The next step is to create a second project to hold the service code and add a post-build event to the project's properties that copies the project's DLL to the folder (I described those steps in my previous column and won't drag you through them again).

The First Service Class
The new service Module project will have an initializer class (a class that Implements the IModule interface) that registers all the service classes that the module provides, using the Unity container that's passed to the initializer class's constructor. When you register a class in a container you specify the interface the class implements, the name of the relationship you're setting up between the interface and the class, and the lifetime manager you're using.

In my previous article I used the ContainerControlledLifetimeManager, which ensured that only one copy of the class would be created for the whole application. That made sense since I was loading a part of my user interface and knew that I'd only ever need one copy of the class. However, I could imagine that a service that supplies, for instance, Customer entities to the application might be created several times. So for this example, I'll use the TransientLifetimeManager, which ensures that an object is created each time it's created.

When I start building an application, I often start by creating a mock data access object that returns dummy data; this lets me test my UI interactions and workflow. So when creating my data access module, I would probably begin with a mock object that returns a fixed set of classes. This code, for instance, which I put in the Initialize method of my Module's initializer class, ties my ICustomerFactory interface to my MockCustomerFactory class using the name MockNWCustomerFactory and a TransientLifeTimeManager:

  Microsoft.Practices.Unity.TransientLifetimeManager tlm = 
   new Microsoft.Practices.Unity.TransientLifetimeManager();
cont.RegisterType(typeof(ICustomerFactory),
                typeof(MockCustomerFactory), "MockNWCustomerFactory", tlm);

To get this code to compile, I'll need to define the ICustomerFactory method and the MockCustomerFactory. For now, I'll just define a single method that returns all the Customers. Since I'm a big fan of data transfer objects, I define a DTO with just the Customer data that the application needs, an interface that includes a method that returns that DTO, and a mock factory object that generates some test data for me (as shown in Listing 1).

The MockCustomerFactory class itself will be one of the classes in my Module project. But that raises the question of where the files holding the DTO and the interface should be put. One choice is the Shell application, and having all the Modules add a reference to that project. A better choice is to create a separate "intfrastructure project" to hold your application's common resources. You can then add references to that project to your Shell and all of your Modules.

I'm now ready to test my application using the mock data returned by my mock class. That raises the question of where that object should be resolved -- a topic I'll address in my next column.

About the Author

Peter Vogel is a system architect and principal in PH&V Information Services. PH&V provides full-stack consulting from UX design through object modeling to database design. Peter tweets about his VSM columns with the hashtag #vogelarticles. His blog posts on user experience design can be found at http://blog.learningtree.com/tag/ui/.

comments powered by Disqus

Featured

  • Visual Studio 2019 for Mac v8.9 Ships with .NET 6 Preview 1 Support

    During its Ignite 2021 online event for IT pros and developers this week, Microsoft shipped Visual Studio 2019 for Mac v8.9, arriving with out-of-the-box support for .NET 6 Preview 1, which the company also released recently.

  • Analyst: TypeScript Now Firmly in Top 10 Echelon (Ruby, Not So Much)

    RedMonk analyst Stephen O'Grady believes TypeScript has achieved the rare feat of firmly ensconcing itself into the top 10 echelon of his ranking, now questioning how high it might go.

  • Black White Wave IMage

    Neural Regression Using PyTorch: Training

    The goal of a regression problem is to predict a single numeric value, for example, predicting the annual revenue of a new restaurant based on variables such as menu prices, number of tables, location and so on.

  • Microsoft Ships Visual Studio 2019 v16.9 Servicing Baseline Release

    Microsoft is urging enterprises and professional coders to standardize on the new Visual Studio 2019 v16.9, a servicing baseline release that's guaranteed to receive official support for an extended period.

Upcoming Events