David Hayden [MVP C#]

Sponsors

The Lounge

News

  • CodeBetter.Com Home

Other Links

Teas

Patterns & Practices

Florida .NET Developer

Book Reviews

Tampa ASP.NET MVC Developer Group

Advertisement

Images in this post missing? We recently lost them in a site migration. We're working to restore these as you read this. Should you need an image in an emergency, please contact us at imagehelp@codebetter.com
Inversion of Control - Dependency Inversion Principle - Castle's Windsor/MicroKernel

Recently I started playing with Castle's Windsor and MicroKernel Inversion of Control Container. MicroKernel is the IOC Container while Windsor helps with external configuration needs such as loading component configurations from an XML file. Although I have yet to use ( decide on ) an IOC Container as part of my default application architecture, I can't help but be impressed with what these tools bring to the table.

Sample Application

If we take a very simple "web application" as shown below, we have an application that is dependent on a blog service. It is not dependent on a particular service / class, only on a service contract represented by IBlogDataService.

 

 

 

For simplicity, the contract is very basic-

 

public interface IBlogDataService
{
    Blog GetBlogByBlogId(int blogId);
}

 

 The Default.aspx page requests the unknown blog service from its purely fabricated, well-known service locator, AppServiceFactory:

 

IBlogDataService service = AppServiceFactory.Instance.Create<IBlogDataService>();

 

AppServiceFactory is a very minimal looking singleton that delegates all the work to Windsor / MicroKernel, which gets its list of components from an XML file ( Components.xml ) that is read at runtime:

 

public sealed class AppServiceFactory
{
    private static AppServiceFactory _instance = new AppServiceFactory();
    IWindsorContainer _container = new WindsorContainer(new XmlInterpreter("Components.xml"));
    
    public static AppServiceFactory Instance
    {
        get { return _instance; }
    }
    
    public T Create<T>()
    {
        return (T)_container[typeof(T)];
    }
    
    private AppServiceFactory()
    {
    }        
}

 

The XML file hides the services and their dependencies:

 

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    <properties>
        <connectionString>myConnectionString</connectionString>
    </properties>
    <components>
        <component id="SqlDatabase"
                        service="BlogDataServices.IDatabase, BlogDataServices"
                        type="DatabaseServices.SqlDatabase, DatabaseServices">
            <parameters>
                <connectionString>#{connectionString}</connectionString>
            </parameters>
        </component>
        <component id="MyBlogDataService"
                        service="WebApplication1.IBlogDataService, WebApplication1"
                        type="BlogDataServices.MyBlogDataService, BlogDataServices" lifestyle="transient" />
        <component    id="HerBlogDataService"
                        service="WebApplication1.IBlogDataService, WebApplication1"
                        type="BlogDataServices.HerBlogDataService, BlogDataServices" lifestyle="transient">
            <parameters>
                <connectionString>#{connectionString}</connectionString>
            </parameters>
        </component>
    </components>
</configuration>

 

Dependency-Inversion Principle and Separated Interface

If we forget about the XML file for a moment and just concentrate on the graphic of the solution above, there is some really warm and fuzzy object-oriented principles and best practices happening that the container allows us to achieve.

First, is the Dependency-Inversion Principle. Rather than the application being dependent on the blog services and the blog services dependent on the database, we have inverted the relationship. The details are no longer in control of the application. The database is dependent on the blog services and the blog services is dependent on the application, allowing us to plug-in various databases and blog services at will without touching the application.

Second, this is all possible due to the use of Separated Interface. The implementation of an interface contract is located separately from the concrete implementations that implement it. Although this is not necessary to achieve our goal of dependency-inversion, is does achieve looser coupling between the parts of the application.

 

Plug-Ins

One of the beauties of these containers is that they provide a pluggable architecture, allowing you to modify an xml file that specifies chosen implementations of service contracts.

The XML file allows me to swap out MyBlogDataService

 

<component id="MyBlogDataService"
                service="WebApplication1.IBlogDataService, WebApplication1"
                type="BlogDataServices.MyBlogDataService, BlogDataServices" lifestyle="transient" />

 

for MyBetterBlogDataService as soon as I come up with it

 

<component id="MyBetterBlogDataService"
                service="WebApplication1.IBlogDataService, WebApplication1"
                type="BlogDataServices.MyBetterBlogDataService, BlogDataServices" lifestyle="transient" />

 

No compiling is necessary.

 

Auto-Wiring of Dependencies

The other obvious benefit of these tools is that they auto-wire dependencies. SqlDatabase is dependent on a ConnectionString:

 

public SqlDatabase(string connectionString)
{
    _connectionString = connectionString;
    
}

 

 and MyBlogDataService is dependent on an implementation of IDatabase:

 

public MyBlogDataService(IDatabase database)
{
    _database = database;
}

 

When I make the following call:

 

IBlogDataService service = AppServiceFactory.Instance.Create<IBlogDataService>();

 

Windsor picks up the default IBlogDataService specified in the XML file, MyBlogDataService, and notices it is dependent on an IDatabase Service. It finds the default IDatabase Service registered, SqlDatabase, and notices it needs a Connection String. It finds the Connection String and injects it to create an instance of SqlDatabase, which is then injected to create an instance of MyBlogDataService. Genius :)

 

Getting Named Service Instances

We can go a step further and grab named instances of services if we don't want the default. Add a method to AppServiceFactory to support this-

 

public T Create<T>(string name)
{
    return (T)_container[name];
}

 

Now I can ask for HerBlogDataService by name:

 

IBlogDataService herService = AppServiceFactory.Instance.Create<IBlogDataService>("HerBlogDataService");

 

Lifestyles

MicroKernel has this cool principle of Lifestyles. By default, a component would have a Singleton Lifestyle. Hence, when you request HerBlogDataService, you will always get the same instance of HerBlogDataService on every request.

However, in the XML file above, you will notice I chose a Transient Lifestyle, which means I want a new instance for each request.

There are other lifestyles supported as well as a custom lifestyle that you specify yourself.

 

Conclusion

You gotta love these inversion of control tools. There are many to choose from if you get the itch to use them in your application architectures.

by David Hayden

 


Posted Fri, Oct 13 2006 8:37 PM by David Hayden

[Advertisement]

Comments

Martijn Boland wrote re: Inversion of Control - Dependency Inversion Principle - Castle's Windsor/MicroKernel
on Sat, Oct 14 2006 6:01 AM

Good to see you like it :).

If you want, you can take dependency injection to an even higher level by also registrating the ASP.NET pages in the container via an HttpHandler. This way you don't need the AppServiceFactory. All that is needed in your example is a setter property for IBlogDataService and everything is wired up automagically.

Ayende Rahien wrote re: Inversion of Control - Dependency Inversion Principle - Castle's Windsor/MicroKernel
on Sat, Oct 14 2006 8:03 AM

Windsor Rocks, yes!

Have you seen what I did with Binsor?

Ayende Rahien wrote re: Inversion of Control - Dependency Inversion Principle - Castle's Windsor/MicroKernel
on Sat, Oct 14 2006 8:07 AM

Here is your configuration in Binsor:

[code]

import BlogDataServices

import DatabaseServices

Component(MyDatabase, IDatabase,

  SqlDatabase).connectionString = "myConnectionString"

Component(MyBlogDataService, IBlogDataService, MyBlogDataService)

Component(HerBlogDataService, IBlogDataService, HerBlogDataService)

[/code]

Dave Donaldson wrote re: Inversion of Control - Dependency Inversion Principle - Castle's Windsor/MicroKernel
on Sat, Oct 14 2006 9:29 AM

I've really been reading a lot about IoC stuff lately and this post definitely helped. Thanks.

David Hayden [MVP C#] wrote Another Inversion of Control Example With Infrastructure and DAO Components
on Wed, Oct 18 2006 4:26 PM

Still tinkering around with Inversion of Control ( IoC ) and Castle&#39;s Windsor/Microkernel and how

ScottBellware wrote re: Inversion of Control - Dependency Inversion Principle - Castle's Windsor/MicroKernel
on Thu, Oct 19 2006 4:38 PM

Though it might sound like a good idea, you should be wary of the named instance features of DI frameworks - at least you shoul dbe careful to create a more type-safe API around it.

In practice, you'll rarely - if ever - need a named instance where the name of the instance doesn't correspond to the name of a class in your app.  You see this in your example with HerBlogDataService.  Using strings to identify known types is a bit too loose.  It will certainly hamper type rename refactoring - regardless of how smart your refactoring tool is in regards to looking for type names in strings.

You'd be better off changing you AppServiceFactory to:

AppServiceFactory.Instance.Create<IBlogDataService>(typeof(HerBlogDataService)

You can get the string "HerBlogDataService" from the type passed into the Create<T> method, and locate the instance in the container based on that string.  This way, you only have to deal with late-binding code in one line of code that is restricted to the single place where the traslation between type names and strings are needed to satisfy Windsor's own API.

ScottBellware wrote re: Inversion of Control - Dependency Inversion Principle - Castle's Windsor/MicroKernel
on Thu, Oct 19 2006 4:44 PM

It kinda seems like the service component is one level on indirection/abstraction more than you would need - especially since your data access is already pluggable by interface.  I'm wondering if this architecture is an artifact of architectures you'd use prior to the enablement that the IoC container brings.

David Hayden wrote re: Inversion of Control - Dependency Inversion Principle - Castle's Windsor/MicroKernel
on Fri, Oct 20 2006 9:36 AM

Scott,

It may be an artifact as I am still tinkering with how to introduce IOC in my applications. Do you have a better way? Alternative solutions are much appreciated :)

.NET Design Patterns and Domain Driven Development wrote Inversion of Control / Dependency Injection
on Sat, May 3 2008 6:59 PM

There&#39;s a ton of great frameworks out there these days for doing Inversion of Control and Dependency