Autofac Decorator Example: How to Configure Your Autofac Container
Autofac Decorator Example: How to Configure Your Autofac Container

Autofac Decorator Example: How to Configure Your Autofac Container

Autofac is a great tool for building Dependency Injection (DI) friendly applications.

It is an IoC container library for .NET that is really simple to use.

It’s simple to register a decorator class using Autofac. The only thing you need to use is the RegisterDecorator method of the builder class.

In this blog post, I’ll show you how to configure your Autofac container to use the decorator pattern, which is a handy way of extending the class’s functionality.

What is a decorator pattern?

The decorator pattern is one of the most popular and well-known design patterns, but for some reason, it doesn’t always seem to get used in production code.

This is a shame because it can be a potent tool for managing complexity.

A decorator pattern is a design pattern in object-oriented programming that allows you to add to or alter the behavior of an object at run time. This can be done by creating another object that contains a decorator and wraps the original object. A decorator pattern is a structural pattern, and it is often used in conjunction with the strategy pattern to provide a choice of interchangeable algorithms.

This pattern is a great option when you want to leave the existing code untouched.

Let’s go over one example to see the decorator pattern in action.

You have the IBookController interface and the BookController class.

interface IBookController
{
    List<string> GetBookNames();
}

class BookController: IBookController
{
    private readonly IBookService _bookService;
    private readonly IOrderService _orderService;

    public BookController(IBookService bookService,
                          IOrderService orderService)
    {
        _bookService = bookService;
        _orderService = orderService;
    }

        public List<string> GetBookNames()
    {
        //some code that retrieves and returns list of book names.
        return new List<string>();
    }

    //other code here...
}

And you get the task to extend the BookController class to implement session management. One way to do that would be to go to the BookController and add the necessary changes.

However, that would add additional responsibility to the BookController, and you don’t want to do that. A better approach would be to wrap the BookController with another implementation of the IBookController. Call this SessionBookController and provide the necessary session management inside this class. This class takes IBookController as a constructor parameter.

class SessionBookController : IBookController
{
    private readonly IBookController _bookController;
    private readonly ISessionService _sessionService;

    public SessionBookController(IBookController bookController,
                                    ISessionService sessionService)
        {
        _sessionService = sessionService;
        _bookController = bookController;
    }

    public List<string> GetBookNames()
    {
        _sessionService.InitializeSession();
        return _bookController.GetBookNames();
    }
}

And you initialize IBookController using the following syntax.

IBookController bookController =
    new SessionBookController(
      new BookController(new BookService(),
                         new OrderService()), 
      new SessionService()
    );

Autofac decorator example

The previous example shows the working code. But the issue is that everything is created manually. And you need to take care of all necessary dependencies.

The solution is to use a DI container such as Autofac.

The first step is to register the BookController class.

var builder = new ContainerBuilder();

builder.RegisterType<BookController>()
                .As<IBookController>().AsSelf();

Next, you can use the RegisterDecorator extension method of the builder to define a decorator class for the IBookController. This means that when someone requests the IBookController, the framework will return the SessionBookController. And the SessionBookController will take BookController as the first constructor parameter.

builder.RegisterDecorator<SessionBookController, IBookController>();

It is also possible to have a decorator chain and register several decorator classes.

builder.RegisterDecorator<LoggerBookController, IBookController>();
builder.RegisterDecorator<SessionBookController, IBookController>();

In this example, LoggerBookController will be applied first, it will wrap the BookController, and the SessionBookController will wrap the LoggerBookController.

Register generic decorator

You can also use Autofac to register the generic classes and interfaces. The following example uses the open generics syntax.

builder.RegisterGeneric(typeof(RegularCommand<>))
        .As(typeof(ICommand<>));

builder.RegisterGenericDecorator(typeof(CommandDecorator<>),
                                    typeof(ICommand<>));

Summary

In this post, you have seen how easy it is to use the decorator pattern with Autofac. Autofac simplifies the process of setting up decorators and makes it easy, quick, and stress-free.

You can easily set up your dependencies without any boilerplate code, which means your code stays decoupled.

But all of this wouldn’t be possible without dependency injection. Read more about dependency injection here, as it’s central to this whole process!