Alex Mueller on Software and Technology 
Sunday, April 02, 2006

According to CastleProject, "You don't." After building a few sites in Monorail, I starting wondering what Inversion of Control (IOC) could do for my development. Obviously IOC is not necessary, since my Monorail sites are working just fine without it, so what's the big deal I thought.

After using Windsor Container in my applications, I am beginning to see the benefits of IOC, and how it makes like easier. The short of it all, both IOC and using a container, is that our objects should not have concrete references to other objects, and they should have their dependencies passed into them. The end goal is a loosely coupled system, whereby using contracts, our components are interchangeable, giving us more testable and portable code. Design principle two in Head First Design Patterns, "program to an interface, not an implementation." If you ask why, read this article A Conversation with Erich Gamma, Part III.

The benefits of the Windsor Container in my application are numerous. The container provides the auto-wiring of classes and their dependencies. How the container encapsulates this logic is not my concern. All I need to know is, when I register a new class instance with it, I know I can expect that component wherever that service is requested in my application. The container injects the dependency into my object, allowing me to easily swap out components that adhere to a given contract.

To see an example, I have created a service, ISiteSecurity, that will provide user and role authentication for my site. The idea behind it is that I can implement a SQL, Oracle, or file system component at my leisure. Here is my interface.

public interface ISiteSecurity
{
    string Source { get; set; }
    bool IsValid(string username, string password);
    bool IsInRole(string username, string role);
}

My class that will implement this interface for this example is below.

public class XmlSiteSecurity : ISiteSecurity
{
    private string source;
    private XPathNavigator navigator;

    public XmlSiteSecurity(string Source)
    {
        this.source = Source;
        this.navigator = new XPathDocument(this.source).CreateNavigator();
    }

    public string Source
    {
        get {return this.source;}
        set {this.source = value;}
    }

    public bool IsValid(string username, string password)
    {
        XPathNavigator nav = this.navigator.SelectSingleNode("/users/user[@username='" + username + "' and @password='" + password + "']");
        
        if (nav != null)
        {
            return true;
        }
        return false;
    }

    public bool IsInRole(string username, string role)
    {
        XPathNavigator nav = this.navigator.SelectSingleNode("/users/user[@username='" + username + "']/roles/role[@name='" + role + "']");

        if (nav != null)
        {
            return true;
        }
        return false;
    }
}

Now let's register the service and component with Windsor Container. In my application's Application_OnStart method, I have the following.

public class MonorailApplication : HttpApplication, IContainerAccessor
{
    public static WindsorContainer container;
    
    public void Application_OnStart()
    {
        container = new WindsorContainer(new XmlInterpreter(new ConfigResource("castle")));
        container.AddFacility("rails", new RailsFacility());
        container.AddComponent("xmlsecurity", typeof(ISiteSecurity), typeof(XmlSiteSecurity));
    }
    
    public IWindsorContainer Container
    {
        get { return container; }
    }
}

Using my web.config, I set the default ISiteSecurity component with the following. To see how this is all configured, consult the Castle site for more details.

<configSections>
    <section name="castle" type="Castle.Windsor.Configuration.AppDomain.CastleSectionHandler, Castle.Windsor" />
</configSections>

<castle>
    <components>
        <component id="xmlsecurity">
            <parameters>
                <Source>C:\Monorail\Website\users.config</Source>
            </parameters>
        </component>
    </components>
</castle>

Now to actually leverage IOC and the Windsor Container, I have the following class. When I reference my service in my application, I request the dependency to be injected into my object's constructor. There are other ways to set this dependency, but I prefer constructor injection. The SignIn method below is used to authenticate my user in this class. When the ContentController is instantiated in my application, Windsor Container passes into it an instance of my XmlSecurity class which implements ISiteSecurity. I then validate users and do what I need. My ContentController class is ignorant of the actual instance of ISiteSecurity.

public class ContentController
{
    ISiteSecurity security;
    
    public ContentController(ISiteSecurity Security)
    {
        this.security = Security;
    }
    
    public void SignIn(string username, string password)
    {
        if (security.IsValid(username, password))
        {
            FormsAuthentication.SetAuthCookie(username, false);
            // redirect to some page
        }
    }
}

By programming to an interface, our implementations can vary, and our system becomes more flexible. Testing becomes easier. Our design is separated from our implementation.

While using Windsor Container or any container for that matter is not necessary, it sure makes life simpler. Using IOC, I can rest easily knowing my objects will get the dependencies they need, regardless of whether the requirements change on me. Windsor Container makes this pretty easy. Check it out for yourself.

Sunday, April 02, 2006 9:48:18 PM (Mountain Standard Time, UTC-07:00) | Comments [0] | Frameworks/Patterns#
MuellerDesigns.net
Search
On This Page
PowerShell Documentation
Automate Daily Tasks with PowerShell
SketchPath XPath Editor
Software Testing - Revisited
Architecting Buildings and Software
NBCOlympics.com with Silverlight
Marker Interfaces and C# Attributes
The Phone Screen
Working with ASP.NET MVC and MvcContrib
Thanks to BDD
Twitter
The Opposite of a Singleton?
Removing Duplicate Code in Functions
Add Vista Themes to Longhorn
Changing File Ownership In Vista and Longhorn
Most Popular
JavaScript ReplaceAll Functionality
What is polymorphism?
What is composition?
Sorting with IComparable and IComparer
Applying the Observer Pattern in ASP.NET
MVP in ASP.NET
What is abstraction?
What is encapsulation?
What is a class?
What is inheritance?
Authentication in ASP.NET
Calendar Controls
XPathNavigator.CheckValidity new for 2.0
SQL Server 2005 Connection Issues
Auto-attach to process '[####] aspnet_wp.exe' on m...
What is an object?
FreeTextBox
VMWare and VPC
An Example of Reflection using C#
Caring for the Team
Archive
Links
Categories
My Local Blog Map
Blogroll
About
Powered by:

Disclaimer
The opinions expressed herein are my own personal opinions and do not represent my employer's view in any way.

© Copyright 2009
MuellerDesigns.net

Sign In

Help Those In Need
The Hunger Site
Ronald McDonald House Charities (RMHC) of Western Washington & Alaska