Login | Register   
Twitter
RSS Feed
Download our iPhone app
TODAY'S HEADLINES  |   ARTICLE ARCHIVE  |   FORUMS  |   TIP BANK
Browse DevX
Sign up for e-mail newsletters from DevX


advertisement
 

Bricks and Mortar: Building a Castle

Discover how to use the Castle Windsor Inversion of Control container to build flexible applications.


advertisement

n an application built with object-oriented techniques, objects are the bricks. You construct little pieces of code encapsulated in these bricks. To build bigger structures, you need to hold these bricks together. You can hardwire them together by instantiating dependent objects within your objects, but it makes the whole structure less flexible in the face of change. But you can adopt an inversion of control (IoC) container that acts as a mason to assemble your bricks into flexible complex structures that adapt easily to changing requirements.

This article examines the popular IoC container "Castle Windsor" to show how it lets you build flexible and robust applications.

If you are new to IoC containers and dependency injection, I would recommend reading Martin Fowler's article, Inversion of Control Containers and the Dependency Injection Pattern and my own article from the March 2008 edition of MSDN Magazine, Loosen Up: Tame Your Dependencies for More Flexible Apps.

Author's Note: The concepts in the article are applicable to IoC containers in general, but the code examples use Castle Windsor 2.0 RTM, which is available from The Castle Project. Castle Windsor 2.0 RTM was not officially released when this article was written, but you can download the latest stable build from the Castle Project Build Server (requires a TeamCity login), or retrieve and build latest source code from the Castle Project Subversion Repository. Note that many of the features discussed are not available in Castle 1.0 RC3, so make sure you get Castle Windsor 2.0 RTM.



IoC Containers perform two basic functions: putting dependencies in and getting fully constructed objects out. First, you'll see how to get fully constructed objects out of a container, and then move on to the more complex aspect of configuring dependencies properly between objects that you place in the container.

Masonry 101

The first job of a container is to respond to your requests for fully constructed objects by resolving their dependencies and cementing them together. Here's a typical request:

var ap = IoC.Resolve<IAccountsPayable>();

When you ask for an implementation of IAccountsPayable, it's the container's job to determine which class implements IAccountsPayable, determine the class's dependencies and any sub-dependencies, and then create instances of all dependencies, building them up as it goes along. Notice that—rather than tying yourself to any particular IoC container—the static gateway pattern decouples the code from a concrete implementation. Let's look at the implementation of IoC in the preceding code. Although IoC is a static class, it forwards all requests to an inner resolver, which is an adapter for the real IoC container:

public static class IoC {
   private static IDependencyResolver resolver;
   public static void Initialize(
      IDependencyResolver resolver) {
      this.resolver = resolver;
   }
   public static T Resolve<T>(){...}
   public static T Resolve<T>(string key){...}
   public static T Resolve<T>(object anonType){...}
   public static T Resolve<T>(string key,
      object anonType){...}
   public static IEnumerable<T> ResolveAll<T>(){...}
}

At application startup, you bootstrap your chosen IoC (in this case, Castle Windsor) using:

var container = new WindsorContainer();
var resolver = new WindsorDependencyResolver(container);
IoC.Initialize(resolver);

Notice that IoC and IDependencyResolver do not have any container configuration methods. All the methods (except Initialize()) are devoted to resolving fully constructed objects. You can get dependencies out, but you cannot get dependencies in. This is because containers vary widely in the way you configure dependencies. It is the job of the bootstrapper to get the container ready to resolve dependencies in a container-specific way before calling IoC.Initialize().

The next sections discuss ways to get objects out of and dependencies into the container.

Editor's Note: This article was first published in the May/June, 2009 issue of CoDe Magazine, and is reprinted here by permission.



Comment and Contribute

 

 

 

 

 


(Maximum characters: 1200). You have 1200 characters left.

 

 

Sitemap