Integrating ObjectBuilder with ASP.NET

September 10, 2007 - 6 minute read -
ObjectBuilder asp.net dependency injection csharp

ObjectBuilder is a .NET framework made for building Inversion of Control or Dependency Injection containers. Unlike Spring or Pico, ObjectBuilder is not a full DI framework, instead it's a framework for building DI solutions. Yes, that's incredibly weird to me too.

Why Use Object Builder?

Why would you use ObjectBuilder instead of a fully baked DI solution? In the .NET world it seems like if it's not built by Microsoft then it's not on the table. People really are looking for the "garden path". So in part it's really a psychological thing. On the other hand the Microsoft Application Blocks and Enterprise Library are built using ObjectBuilder. So, if you are already using some of those solutions, then you already have a dependency on ObjectBuilder. It is natural to try to control the number of dependencies that a project relies upon. In this case, you have a simple solution that just requires a bit of custom code.

In addition to the fact that it's basically a roll-your-own DI framework, the other downside of ObjectBuilder is that the documentation is non-existent. It's said 'Under construction...' sine July of 2006, so don't get your hopes up if you don't want to look at the API and read the source.

Wire Together Services

If you are going to build a service you could do property based injection. What this means is that in your service layer all of the dependencies are passed into a service via property setters. This keeps the code clean and makes changing the implementation of a dependency very easy. If you have a hardcoded constructor for your dependency in a class then making this kind of change will be harder. It also makes Unit Testing very easy because you can mock out dependencies and isolate the layers of your code.

public class SomeService
{
    private SomeDAO someDao;
    [Dependency]
    public SomeDAO SomeDAO
    {
        get { return someDao; }
        set { someDao = value; }
    }</p>
<p>    public void Save(SomeObject o)
    {
        if (o.IsValid)
            SomeDAO.Save(o);
    }
}

ASP.NET

Most of the examples you can find on the web dealing with ObjectBuilder are about how to use ObjectBuilder as a ServiceBroker where you instantiate a service type object in a view.

public partial class SomePage : System.Web.UI.Page
{
    private SomeService someService;
    protected void Page_Load(object sender, EventArgs e)
    {
        Builder builder = NewBuilder();
        someService = builder.BuildUp<SomeService>(null, null, null);
    }</p>
<p>    private Builder NewBuilder()
    {
        // Create a Builder
    }
}

While that's ok, I think it's a pretty limiting way to do things. Once you get to any sort of complex object construction, you are going to have to create another class to encapsulate all of the policies and strategies for building objects. The other issue is that using the Services in UI code is very different than compositing the services themselves. It also stands in stark contrast to the clean implementation of the Service layer.

I want to make my pages look more like my Service layer.

public partial class SomePage : System.Web.UI.Page
{
    private SomeService someService;
    protected void Page_Load(object sender, EventArgs e)
    {
    }</p>
<p>    [Dependency]
    public SomeService SomeService()
    {
        get { return someService; }
        set { someService = value; }
    }
}

IHttpModules to the Rescue

Page lifecycles are handled by the ASP.NET worker processes so there is no way to construct your own pages and do the Dependency Injection. I immediately went to the idea of a filter (which is how this is done in the Java world). The filter concept in ASP.NET is implemented as an IHttpModule.

The module should do 2 main things:

  • Construct and manage the DI container
  • Inject Properties into the Page object that is going to handle the request

Construct a series of ObjectBuilder classes to create your DI container.

Locator locator = new Locator();
ILifetimeContainer container = new LifetimeContainer();</p>
<p>// Setup the strategy for how objects can be created
BuilderStrategyChain chain = new BuilderStrategyChain();
chain.Add(new CreationStrategy());
chain.Add(new PropertyReflectionStrategy());
chain.Add(new PropertySetterStrategy());
locator.Add(typeof(ILifetimeContainer), container);</p>
<p>// Create a context to build an object
BuilderContext builderContext = new BuilderContext(chain, locator, null);
builderContext.Policies.SetDefault<ICreationPolicy>(new DefaultCreationPolicy());

You can access the current Page that will handle the request in an IHttpModule using:

HttpApplication app;
app.Context.CurrentHandler; // The Page handler

Now to tie it all together we create an IHttpModule that will filter each request and wire up our Pages with their dependencies. IHttpModules are configured to respond to callback events related to the Life Cycle of a request. In this case we need wire up our Pages after the PostMapRequestHandler because the Page is created prior to this. I set this up on the PreRequestHandlerExecute because everything is setup at this point and it is right before the Page methods are called.

///
<summary>
/// ObjectBuilderModule handles PropertyBased Injection for ASP.NET Forms.
/// </summary>
public class ObjectBuilderModule : IHttpModule
{
    private HttpApplication app;
    private readonly Locator locator = new Locator();
    private readonly ILifetimeContainer container = new LifetimeContainer();
    private readonly BuilderStrategyChain chain = new BuilderStrategyChain();
    private readonly BuilderContext builderContext;
    public ObjectBuilderModule()
    {
        chain.Add(new CreationStrategy());
        chain.Add(new PropertyReflectionStrategy());
        chain.Add(new PropertySetterStrategy());
        locator.Add(typeof(ILifetimeContainer), container);
        builderContext = new BuilderContext(chain, locator, null);
        builderContext.Policies.SetDefault<ICreationPolicy>(new DefaultCreationPolicy());
    }</p>
<p>    public void Init(HttpApplication context)
    {
        app = context;
        // PreRequestHandler so that everything is setup including the Session, etc
        app.PreRequestHandlerExecute += InjectProperties;
    }</p>
<p>    void InjectProperties(object sender, EventArgs e)
    {
        IHttpHandler h = app.Context.CurrentHandler;
        if (h is DefaultHttpHandler)
            return;
        chain.Head.BuildUp(builderContext, h.GetType(), h, null);
    }</p>
<p>    public void Dispose()
    {
        app.PostMapRequestHandler -= InjectProperties;
    }
}

Conclusion

Hopefully this shows you that you can create a powerful, transparent solution for doing Dependency Injection with ASP.NET. This isn't necessarily a complete solution. We could implement many other things like Singleton management for various service classes for example. Now all you have to do is extend it for your application's own needs.