Autofac 2.4 is just around the corner, with beta builds now available via the project site (the short list of changes since 2.3 is available here.) One of the enhancements coming with this release is improved support for wiring up components in the Decorator Pattern.
Circa Autofac 2.2 we introduced container support for the Adapter Pattern. An Adapter takes a service and exposes its functionality through a different interface. While it has always been possible to implement adapters in Autofac using the basic APIs, adding container support for “bottom-up” composition makes it easier to implement adaptation reliably on all implementations of an adapted service.
Decorators are a similar story. Given an implementation of a service, a decorator takes that implementation and modifies its functionality, exposing the same interface.
class CommandHandler : ICommandHandler { }
class TransactedCommandHandler : ICommandHandler {
public TransactedCommandHandler(
ICommandHandler decorated,
ISession session) { }
}
Here the TransactedCommandHandler is a decorator for the ICommandHandler service, that adds transaction management via a persistence session. The CommandHandler component provides the actual implementation of the service.
Decorators by Hand
In Autofac the components for this scenario can be registered without any special decorator support:
builder.RegisterType<CommandHandler>()
.Named<ICommandHandler>("implementor");
builder.Register(c => new TransactedCommandHandler(
c.ResolveNamed<ICommandHandler>("implementor"),
c.Resolve<ISession>())
.As<ICommandHandler>();
This takes advantage of a named service to identify the implementor, and thus link it up to its decorator which is registered to provide the service type (not named.)
Clean and straightforward – and recommended if your scenario is as simple as the one above. If you have more than one component that you’d like decorated, or want to use decorators with open generics, then things can get more complicated rather quickly.
Drawing on a lot of inspiration from the design philosophy of MEF, Autofac has good support for handling n things like this. In 2.4, we use that support to automate some of the process of configuring decorators.
IoC Design Tip: When you’re looking for abstractions to use as services in an application, prefer those that describe a set of related things. Zero-or-more type relationships are less brittle in the face of change than exactly one or zero-or-one relationships.
RegisterDecorator() and RegisterGenericDecorator()
There are two new registration methods for decorators in Autofac 2.4 – a non-generic and a generic version.
The non-generic version, when applied to the scenario above, looks like:
builder.RegisterType<CommandHandler>()
.Named<ICommandHandler>("implementor");
builder.RegisterDecorator<ICommandHandler>(
(c, inner) => new TransactedCommandHandler(inner, c.Resolve<ISession>()),
fromKey: "implementor");
The first thing you’re probably thinking is “hey, this isn’t any less code than the old way!” That’s very likely true, but reducing the amount of code involved wasn’t a goal here.
The difference between this code, using RegisterDecorator and the first example is that this version decorates all implementations of ICommandHandler, so if additional command handlers are registered (using the “implementor” name) then they will each get their own decorator.
There are some diagrams in the adapter article previously linked that describe the object graph structure; reading that article will shed some light on what I’m talking about here if the details are a bit foggy.
RegisterDecorator() works a lot like Autofac’s typical delegate-based component registration methods. The things to note are:
- The generic parameter (here
ICommandHandler) is the service that is being decorated. - The method accepts a delegate that, given the context
cand the implementation of the service being decoratedinner, produces an instance of the decorator. - The final pair of parameters are
fromKeyandtoKey(optional) that describe where this decorator sits in the chain from implementation up to the topmost decorator. This works the same way as in the decoration-by-hand example earlier.
RegisterGenericDecorator() is similar to its non-generic counterpart, but deals with cases where the decorated service is an open generic one. Given a generic alternative to the earlier example:
class CommandHandler<TCommand> : ICommandHandler<TCommand> { }
class TransactedCommandHandler<TCommand> : ICommandHandler<TCommand> {
public TransactedCommandHandler(
ICommandHandler<TCommand> decorated,
ISession session) { }
}
Setting up the same decorator structure is done using:
builder.RegisterGeneric(typeof(CommandHandler<>))
.Named("implementor", typeof(ICommandHandler<>));
builder.RegisterGenericDecorator(
typeof(TransactedCommandHandler<>),
typeof(ICommandHandler<>),
fromKey: "implementor");
It is worth noting that while the decorator is an open generic type, the decorated components don’t have to be. So, if there are concrete command handler types:
.Named<ICommandHandler<AddCommand>>("implementor");
The generic decorator will be applied to each concrete implementation as expected.
There are other ways of implementing decorator support and different choices that can be made about how the APIs should work. There are certainly some big trade-offs made in this implementation; in most of them, simplicity and orthogonality trumped concision or ‘magic.’ A discussion of these decisions almost made it into this article, but I worried about this obscuring the more useful and concrete content. If you have any questions about why things are done this way please do post a comment!

Totally love this! Feels good to finally be able to get rid of all the “Expression” stuff in OnActivating().
[...] Decorator Support in Autofac 2.4 (Nicholas Blumhardt) [...]
@seagile That’s great!
[...] new and improved decorator support makes it much easier to wire up generic decorators with Autofac, and also provides a nice boost [...]
Is there a reason the fromKey parameter is required? Does the service to be decorated have to be registered using a named key?
@Jimit no – you can pass a null fromKey. The API might be better if it was also an optional argument – but there’s always a need to supply either from or to.
Maybe my question is more about named services but…
We have multiple hosts/clients where some common services are registered in common autofac modules shared by all hosts. Then each hosts adds “extra” services unique for each client.
When trying to use this decorator support in autofac, I run into problem like this…
In “shared” code…
builder.RegisterType().As();
..in some “client” code I want to decorate this service due to something specific in this host…
builder.RegisterDecorator(…..);
The “problem” is that in some clients there should be no decorators so in “shared” code I don’t want to give a specific name to the service. But if I don’t, I need to give a specific name to decorated instance which isn’t optimal due to other components dependencies to IA.
What I want (I think) is a chance to…
builder.RegisterType().As();
builder.RegisterDecorator(.., fromKey=null, ..);
builder.RegisterDecorator(….);
builder.RegisterDecorator(….,toKey=”something”);
builder.RegisterAsDefaultFor(“something”);
Assert.AreSame(sameInstanceAsLastRegisterDecoratorAbove, container.Resolve());
Is there any way to accomplish this in autofac already?
Oops. Comments don’t seem to like “<” and “>”…
I get the following error when using a nameless implementer and decorator:
The service XXX cannot be both the adapter’s from and to parameters – these must differ.
RegisterType().As();
RegisterDecorator(inner => new XXX2(inner), null);