ClientUI 7 Preview Part 1: Built-in IoC Containers

Since its debut two years ago, ClientUI has been designed to facilitate application development toward loose coupling approach. This can be seen from the comprehensive MVVM-ready components and application framework included in ClientUI, then followed with the introduction of Event Aggregator in the latter release. In addition, most of our samples and tutorials are built with the MVVM design pattern as well. In the upcoming releases, we’ll take the design pattern to the next level by introducing a lightweight IoC container which is integrated to many important aspects of the ClientUI application framework.

In this blog post, I’m excited to share what ClientUI has to offer in the next major release. I will focus on the framework enhancements and new advanced library specifically designed to enable you write maintainable code with maximum loose coupling. Before I introduce these new libraries, I’ll discuss the basic purposes of the loose coupling design pattern, so you can see what the new library does, and how it addresses the programming challenges.

Dependency Injection Demystified

Unless you write prototypes or applications that never make it past release 1, you’ll
soon find yourself maintaining and extending existing code bases. To be able to work
effectively with such a code base, it must be as maintainable as possible. One of many ways to make code maintainable is through loose coupling. In short, the main point is that loose coupling makes code extensible, and extensibility makes it maintainable.

One of many techniques to enable loose coupling is Dependency Injection (often called as DI). A lot have been said and written about DI these days – it’s fascinating how most of these literatures make DI sound so complicated, yet it’s really simple in reality. Powerful yet simple. In this blog post, I hope to be able to give a decent and clear explanation about DI and its main concept, and how it differs from Inversion of Control (IoC).

Let’s dive in. Assume you run a new business that started using PayPal as your payment provider. Naturally, you’ll create a website that processes the transactions online, hence the following code.

public class MyStore
{
    public bool ProcessTransaction(Transaction trans)
    {
        PayPalPaymentProcessor paymentProcessor = new PayPalPaymentProcessor();
        return paymentProcessor.ProcessPayment(trans);
    }
}

The code above is very simple and straightforward, and does the job pretty well. First, it instantiates a new PayPalPaymentProcessor class and then call the ProcessPayment method. Nothing’s wrong.

As your business grows, you’d like to switch to different payment processor (or add a new option), let’s pick Google Checkout as an example. To make this happen, it’s obvious that you’ll have to find the piece of code that processes the transaction, modify the code to introduce the new payment option and rebuild your project. You’ll probably come up with the following results.

public class MyStore
{
    public bool ProcessTransaction(string type, Transaction trans)
    {
        if (type == "PayPal")
        {
            PayPalPaymentProcessor paymentProcessor = new PayPalPaymentProcessor();
            return paymentProcessor.ProcessPayment(trans);
        }
        else if (type == "Google")
        {
            GooglePaymentProcessor paymentProcessor = new GooglePaymentProcessor();
            return paymentProcessor.ProcessPayment(trans);
        }
        else
        {
            throw new ArgumentException("Payment processor not supported", "type");
        }
    }
}

Again, there’s nothing wrong with the code above as it does the job pretty well. However, doing the job well doesn’t always mean it has met the requirements to build good applications, for instances, in terms of maintainability and extensibility. In the case above, the code wasn’t really maintainable as you have to repetitively make changes on the same piece of code when you add new payment processors. This, naturally, makes your application more difficult to extend, not to mention if you want to hand over the code to be maintained by different developers.

Architecturally, the main problem with the code above is the referenced dependencies where the MyStore class depends on the concrete payment processor class such as PayPalPaymentProcessor or GooglePaymentProcessor. The concrete type dependency makes it impossible for you to plug-in new payment processors without modifying the code. So what we’re going to do next is take out the dependencies and revamp our code into the following.

public class MyStore
{
    public MyStore(IPaymentProcessor paymentProcessor)
    {
        if (paymentProcessor == null)
            throw new ArgumentNullException("paymentProcessor");

        this.PaymentProcessor = paymentProcessor;
    }

    public bool ProcessTransaction(Transaction transaction)
    {
        return this.PaymentProcessor.ProcessPayment(transaction);
    }

    protected IPaymentProcessor PaymentProcessor { get; set; }
}

Now what do you think? Looks much neater and easier to read, isn’t it? In the code above, the dependencies to the concrete types have been eliminated and replaced by the interface abstraction of the payment processor. The MyStore class now requires the payment processor to be passed in the constructor, which is a common technique known as constructor injection while the Guard in the constructor ensures a valid instance of payment processor is passed, thus ensuring the availability of the payment processor when consumed throughout the methods in the class. Ultimately, this resolution also addresses the extensibility issue as you can now instantiate the payment service externally and simply pass-in the instance.

In essence, the technique of passing (or injecting) the instance (PaymentProcessor) on to the depending class (MyStore) class is called Dependency Injection.

As we’ve just demystified the DI concept, it’s now becoming clear that DI has nothing to do with Inversion of Control (IoC) or any other programming frameworks, although in reality, both are often paired together to achieve the ultimate design goal – “Loose Coupling”.

At this point, still using the payment service scenario above, you will likely consume the MyStore class by instantiating it through manual construction. At the simplest, the code will look like:

public class MainPageViewModel : ViewModelBase
{
    private void ExecuteProcess()
    {
        MyStore myStore = new MyStore(new PayPalPaymentProcessor());
        myStore.ProcessTransaction(transaction);
    }
}

While the code above is much neater and easier to read, there’s still one last problem that violates the law of loose coupling design pattern. Without you realizing it, the MainPageViewModel class (the consumer) now depends on two classes: MyStore and PayPalPaymentProcessor.

Eliminating the dependencies completely in such scenario can be achieved by inverting the flow of control of the system in a way where the objects and its dependency graphs can be instantiated through an external assembler. This technique is called Inversion of Control (further abbreviated as IoC), and that’s where the IoC containers comes into the picture.

IoC Container Comes to the Rescue

IoC is a design pattern that inverts the flow of the application logic, which is achieved through the use of Dependency Injection for its binding process. This approach allows maximum loose coupling where dependencies can be minimized or completely eliminated. This also means that such code allows great extensibility as the concrete implementation can be easily swapped at runtime.

The payment service scenario earlier with the state where it left off is perfectly ideal for our IoC example, so let’s move on revamping our code and see what IoC container has to offer, see the following code.

public class MainPageViewModel : ViewModelBase
{
    private void ExecuteProcess()
    {
        IStore store = Container.Resolve<IStore>();
        store.ProcessTransaction(transaction);
    }
}

To remove dependencies on concrete implementation, one of the common approaches is by abstracting the implementation into abstract class or interface, as shown in the code above. Leveraging IoC container in this piece of code enables us to resolve an instance of the concrete store implementation – anywhere and anytime when required in the business logic flow – without knowing the exact type that contains concrete implementation. This is so powerful because it allows you to change the concrete implementation externally without ever touching this piece of code.

At the heart of IoC container are the Register and Resolve methods, which perform the following:

  • Register: Register a dependency by associating the abstract type or interface to the concrete type
  • Resolve: Resolve an instance of the dependency by looking up the exact registration in the container

Most of the dependency registrations are usually done in a centralized place, commonly invoked when the program initializes. This centralized place is called Composition Root, which allows you to manage the composition of all components and services in a single place. Using the payment service scenario above, the registration looks like the following.

public class AppInitializer : IApplicationInitializer
{
    public void Initialize(ApplicationPackage package)
    {
        IDependencyContainer container = UXShell.Current.Container; // or new IocContainer() for standalone container;

        // Register the IStore interface to compose a new PayPalPaymentProcessor through a direct construction
        container.Register<IStore>(o => new MyStore(new PayPalPaymentProcessor()));
    }
}

The code above is self explanatory – it registers the IStore interface type to a function that returns a new MyStore class complete with the required dependencies which is the PayPalPaymentProvider in this case.

The IoC container along with a set of comprehensive APIs are the new libraries introduced in next major release of ClientUI. It features full-blown IoC container features yet lightweight enough to deliver high-performing and scalable applications. At a glance, the key features are:

  • High-performance object factory
  • Abstract and interface type resolution
  • Open generic support
  • Instance-based resolution
  • Lazy resolution
  • Named containers
  • Lifetime Manager

Integration with ClientUI Application Framework

The IoC container implemented in the ClientUI Framework supports both standalone usage and integration with UXShell. For most common scenarios, it’s recommended that you use the default container instance which is accessible from the shell’s RootApplication.Container property. Using this approach enables you to resolve the registered dependencies anywhere in your code, including the dynamic XAP applications that are loaded on demand at runtime. Click here to learn more about ClientUI Application Framework.

In addition, the application framework now introduces a built-in bootstrapper to facilitate the dependencies composition and registration. Simply add a class that implements IApplicationInitializer interface in your Silverlight project, the Initialize method will be invoked as the application starts. In dynamic XAP scenario, the Initialize method will be automatically invoked when the XAP package is downloaded and loaded to the application domain.

Download Sample Code

In summary, the combination of design pattern best practices – such as MVVM, Event Aggregator, Dependency Injection and Inversion of Control – along with extensible application framework enable you to build great business applications that are easily maintainable and extensible. We see this as important milestones in our development roadmap as we geared our tools toward enterprise and line-of-business apps.

Another important point to keep in mind is that these design patterns aren’t exclusive only for Silverlight or WPF platforms although I picked Silverlight for the samples. We will bring forward these patterns to new platforms as they become available.

To test drive the DI concept and IoC container, I’ve prepared a small Silverlight sample that demonstrates how to achieve good architectural design by implementing Inversion of Control through Dependency Injection. The download package also includes the developer preview version of ClientUI Framework. Click here to download the sample package, and feel free to ask any questions or provide feedback in the comment box below.

In the next series of my blog post, I’ll discuss about several interesting new stuff such as View Regions, View Discovery and View Injection – and how they play well with IoC containers. Stay tuned.

Warning: Do not use the preview Framework assembly in your “live” projects as it will cause version incompatibility issues with the other assemblies in the current release.

All the best,
Jimmy
Chief Software Architect

Advertisements

One thought on “ClientUI 7 Preview Part 1: Built-in IoC Containers

  1. Pingback: ClientUI Preview Part 3: Pageable and Multi-column ComboBox, Enhanced GridView, Items Grouping and more | Intersoft Solutions Corporate Blog

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s