This post was published on an earlier personal blog, no longer online. ‘Caraway’ grew up and became Autofac, still an active and evolving open-source project. You can watch the design begin to evolve in this follow-up post, and next post after that shows the beginnings of Autofac’s lifetime model.

I think I’ve said previously that no IoC container in .NET land has really grabbed me so far. Like a typical programmer :) I’ve gone and tricked up my own.

Caraway is small and simple, aimed at providing a ready-made extensibility subsystem. It should fit in wherever ‘enterprise’ is just too much bulk. The design is flexible and could probably incorporate AOP or locational transparency without too many changes, but people are already doing a good job in those areas elsewhere.

Caraway is also incomplete - there are some core features such as named components that remain unimplemented. There are some nifty extras in there too, with more in the pipeline.

Overall the design philosophy of Caraway is to encourage programmatic configuration through a terse API. Autowiring, based on reflective use of the type system, is used as a workhorse to reduce the amount of code a programmer has to write.

I’ve also sacrificed flexibility in places to make the library suited to the kinds of systems I write. It is expected, though not required, that all components will be accessed through general interfaces. (If you stop and think about it, this makes a lot of sense as there is no point using a tool that enables decoupling when your components are tied together with concrete type dependencies.)

The first example I’ll give uses Caraway to instantiate a couple of related components:

using System;
using Caraway;

interface ILogger
{
  void Write(string message);
}

class ConsoleLogger : ILogger
{
  public void Write(string message)
  {
    Console.WriteLine(message);
  }
}

interface IAuthenticator
{
  bool Login(string username);
}

class NickAuthenticator : IAuthenticator
{
  private ILogger _logger;

  public NickAuthenticator(ILogger logger)
  {
    _logger = logger;
  }

  public bool Login(string username)
  {
    _logger.Write("Login attempt by " + username + "...");
    if (username == "nick")
    {
      _logger.Write("...successful.");
      return true;
    }
    else
    {
      _logger.Write("...failed.");
      return false;
    }
  }
}

public class Program
{
  public static void Main(string[] args)
  {
    IInjectionContainer c = new InjectionContainer();

    c.Register<IAuthenticator>(typeof(NickAuthenticator));
    c.Register<ILogger>(typeof(ConsoleLogger));

    c.Resolve<IAuthenticator>().Login("nick");

    Console.ReadKey();
  }
}

The code prints:

Login attempt by nick...
...successful.

The InjectionContainer gets asked for IAuthenticator. Seeing that NickAuthenticator was registered to provide this service, the container creates an instance using the registered ILogger type to satisfy the constructor dependencies.

I’ll be posting some more in-depth how-to articles on Caraway in the coming weeks. Subversion access isn’t available yet, so if you have any ideas or patches you’d like applied, please post a comment on the project page.