What's This Do?

Programming etc.

Why Autofac is Awesome.

And I mean “awesome” with an “awe”.

Autofac allows you to create true façades.

Consider this trivial interface, for printing things,

namespace IoCExample
{
    public interface IPrinter
    {
        void Print (string text);
    }
}

and this implementation,

namespace IoCExample
{
    public class TextPrinter : IPrinter
    {
        TextWriter _writer;

        public TextPrinter (TextWriter writer)
        {
            _writer = writer;
        }

        public void Print (string text)
        {
             _writer.WriteLine (text);
        }
    }
}

Now take this façade, which isn’t actually much of a façade but serves as an example,

namespace IoCExample
{
    public interface IGreeter
    {
        void SayHello();
    }

    public class Greeter : IGreeter
    {
        IPrinter _printer;

        public Greeter(IPrinter printer)
        {
            _printer = printer;
        }

        public void SayHello()
        {
             _printer.Print("Hello");
        }
    }
}

Autofac allows you to wrap up the instantiation of these classes in such a nice way; you can build an IGreeter without needing to know:

  • what the implementation of IGreeter is,
  • that the IGreeter uses an IPrinter, or
  • that IPrinter or TextPrinter even exist.

The one thing you do need to know is,

  • that you can get an IGreeter by providing a TextWriter as an argument.

Here is an example usage:

namespace IoCExample
{
    class Foo
    {
        public Foo(Func<TextWriter, IGreeter> greeterFactory)
        {
            // greet the console!
            IGreeter greeter = greeterFactory (Console.Out);
            greeter.SayHello ();
        }
    }
}

Use this Autofac hookup code:

            ContainerBuilder builder = new ContainerBuilder();

            // Register the IGreeter implementation
            builder.Register<Greeter>((c, p) =>
                new Greeter(c.Resolve<IPrinter>(p))).As<IGreeter>();

            // Register the IPrinter implementation
            builder.Register<TextPrinter>((c, p) =>
                new TextPrinter(p.TypedAs<TextWriter>())).As<IPrinter>();

            // Use Foo
            builder.RegisterType<Foo>();

            IContainer container = builder.Build();
            container.Resolve<Foo>();

Autofac takes care of it for us, which is just great, right?

The beauty of the code above is that you could swap out Autofac for an equivalent Dependency Injection container at any point, without upsetting any of your code.

Here’s the equivalent code to the previous snippet, only without using any IoC libraries:

Func<TextWriter, IGreeter> greeterFactory = wr => new Greeter (new TextPrinter(wr));
new Foo (greeterFactory);

In this example it’s only a couple of lines, but it quickly become unmanageable if you want to be instantiating Foos all over the place, and especially if Foo is higher up in the DI chain. And if you want to swap out your Greeter implementation (say, for a multi-lingual one) you’ll need to change it everywhere. Also, you now need to know what a TextPrinter is and what the implementation of IGreeter looks like, just to create a Foo!

Autofac is better.

Follow

Get every new post delivered to your Inbox.

Join 230 other followers