Posts by Nicholas Blumhardt

Decorator Support in Autofac 2.4

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.

interface ICommandHandler { }

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.

Decorator structure

Decorator structure

Decorators by Hand

In Autofac the components for this scenario can be registered without any special decorator support:

var builder = new ContainerBuilder();

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:

var builder = new ContainerBuilder();

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 c and the implementation of the service being decorated inner, produces an instance of the decorator.
  • The final pair of parameters are fromKey and toKey (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:

interface ICommandHandler<TCommand> { }

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:

var builder = new ContainerBuilder();

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:

builder.RegisterType<AddCommandHandler()
    .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!

Autofac Project Status Update

Autofac 2.4 Coming Soon

Sometime early in the New Year we’ll be releasing a new version of Autofac.

The star of the show in Autofac 2.4 is a much revamped ASP.NET MVC implementation by Alex Meyer-Gleaves, optimised for use with the MVC3 release. This promises a much quicker, simpler and more robust setup process, finally ridding us of the dependency on an HTTP module (Web.config change) for lifetime control.

Also included in Autofac 2.4 is support for decorators, including some pretty sophisticated coverage of open generic decorator scenarios. In earlier versions of Autofac the very useful Decorator pattern could be a little awkward to implement – I’ll be writing more soon about how Autofac 2.4 tidies this up.

Finally, the new release will continue our recent efforts to improve error messages and bring more consistency and completeness to the APIs introduced in the 2.x series, such as the assembly scanning support. There are no planned breaking changes.

NuGet Packages

Through distribution with ASP.NET MVC3, the NuGet package manager is rapidly gaining traction as the standard way to distribute open source projects for .NET. Thanks to the pioneering efforts of some of the Autofac community there are packages for:

  • Autofac, including its WCF and MEF integrations, for .NET 3.5/4.0 and Silverlight 3/4 (Autofac)
  • Autofac with ASP.NET MVC2 for .NET 3.5/4.0 (Autofac.Mvc2)
  • Autofac with ASP.NET WebForms for .NET 3.5/4.0 (Autofac.Web)

While we expect to fine tune the packages along with the upcoming 2.4 release, you can certainly use NuGet today if you want to use Autofac in your projects.

Open Generics and Autofac 2.3

Autofac 2.3 hit the shelves more than three months ago but as it coincided pretty closely with the birth of our daughter Vera I didn’t write much about it at the time.

One improvement worth mentioning is the much-expanded support for open generic components, contributed by Rikard Pavelic. I answered a recent question on the Autofac mailing list with “it can’t be done” only to find later that the scenario being discussed was already supported. Though fairly unusual, it is an interesting feature so I’ll describe it below, but first the less exotic cases.

Generic Parameter Constraints

C# allows the arguments of a generic type to apply constraints that parameters must match. For example, we might constrain an event handler implementation to a type of event:

interface IEventHandler<in TEvent> {
    void Handle(TEvent @event);
}

In this small example we have an interface that helps us dispatch event objects to handlers. Typically there would be one or more handlers for each event type, most of them specific to the kind of event. We also have a marker interface for events that should trigger some kind of auditing, and a handler that will make this happen.

interface IAuditableEvent { }

class AuditingEventHandler<TEvent> : IEventHandler<TEvent>
        where TEvent : IAuditableEvent {
    void Handle(TEvent @event) {
       // Write an audit record…
    }
}

Note that the handler uses a generic type constraint to select the kind of events it is interested in. Some events will be auditable, others not:

class ItemAddedToCartEvent { }

class CheckoutCompletedEvent : IAuditableEvent { }

The AuditingEventHandler<TEvent> will be registered as an open generic type.

var builder = new ContainerBuilder();
builder.RegisterGeneric(typeof(AuditingEventHandler<>))
    .As(typeof(IEventHandler<>));
var container = builder.Build();

Assuming that we’ve registered all of the different event handlers for the above two events, what should happen when we resolve all of the handlers for ItemAddedToCartEvent?

var handlers = container.Resolve<IEnumerable<IEventHandler<ItemAddedToCartEvent>>>();

The AuditingEventHandler<TEvent> component is registered to provide the IEventHandler<TEvent> service, but the generic type constraint doesn’t match. In earlier versions of Autofac, the above line would have raised an exception.

With support for open generic parameter constraints, Autofac will now instantiate only the types whose constraints match, so the handlers collection above would be returned successfully without any attempt to instantiate the AuditingEventHandler<TEvent>.

If instead an auditable event is to be handled, then the auditing handler would be included:

// Succeeds and returns an AuditingEventHandler<CheckoutCompletedEvent>
var handlers = container.Resolve<IEnumerable<IEventHandler<CheckoutCompletedEvent>>>();

Constraint Types

Autofac 2.3 handles all of the generic parameter constraints you’re likely to encounter, including:

  • new()
  • class and struct
  • Base type and implemented interfaces

Parameter Binding Solver

Open generic types are more subtle and complicated to support than they sometimes appear. Take this contrived but not unimaginable example:

class MonoDictionary<T> : IDictionary<T,T> { }

The generic parameter T appears twice in the parameter list of the implemented IDictionary<TKey,TValue>! That means if we register MonoDictionary<T>:

builder.RegisterGeneric(typeof(MonoDictionary<>))
    .As(typeof(IDictionary<,>));

Then we should be able to resolve IDictionary<int,int> but not IDictionary<int,string>. Tricky – but as of version 2.3, Autofac can handle it.

The example we discussed on the Autofac mailing list was something like:

interface IProducer<T> { }

class NullableProducer<T> : IProducer<T?>
    where T : struct { }

The twist here is that the generic component NullableProducer<T> does not parameterise IProducer<T> directly with T, but rather Nullable<T> (abbreviated to T?).

This means that if we resolve IProducer<int?> then NullableProducer<int> should be activated, while resolving IProducer<int> should ignore NullableProducer<T> altogether.

Autofac 2.3 also supports this case, with some terse but surprisingly succinct code. Hopefully this will open up some new, richer generic component possibilities.

Coming in Autofac 2.3 – OnRelease()

Most components that need to be cleaned up implement IDisposable, which Autofac will use when the component is due to be released. Some components however, notably WCF client proxies, have non-standard ‘release’ behaviour.

There have never been enough cases of these non-standard components to justify messing with the Autofac core model to provide custom release behaviours, so for some time (six major versions, in fact) this hasn’t been added.

Happily, for WCF proxies and other components like them, a simple implementation has been found that allows a custom release action to be piggy-backed on a regular disposable component, so in Autofac 2.3 (currently in preview) we’ll be offering OnRelease() for the first time:

builder.Register(c => CreateWcfClient())
    .As<IClient>()
    .OnRelease(client => ReleaseWcfClient(client));

Simple addition – hopefully a pleasant improvement in these scenarios.

For the curious, WCF client proxies require that calls to Dispose() be wrapped in try/catch blocks so that exceptions during disposal don’t obscure any other exceptions thrown during the use of the proxy itself. Not fun stuff, but relax, the Autofac.Integration.Wcf assembly now includes an implementation of UseWcfSafeRelease() as well.

Speaking at Tech.Ed Next Week

Just a quick note for anyone who happens to be visiting Tech.Ed on the Gold Coast next week. I’ll be presenting a session at 11:00 AM Thursday with the vague and unfortunately grandiose title DEV426: The Art and Engineering of Supple Enterprise Applications. Fear not – that’ where the abstraction ends; we’ll be digging into the concrete and sometimes gritty details of “programming in the large” with IoC. There should be something for veterans and newbies alike – I hope you can make it!

The IIndex<K,V> Relationship Type

Component metadata, which is consumed via the Lazy<T,M>, Meta<M> or Meta<T,M> relationship types, gives us a way to choose between available components based on some criteria:

class Browser
{
    IEnumerable<Lazy<IViewer, IViewerMetadata>> _viewers;
   
    public Browser(IEnumerable<Lazy<IViewer, IViewerMetadata>> viewers)
    {
        _viewers = viewers;
    }
   
    public void OnViewFile(string filename)
    {
        var ext = Path.GetExtension(filename);
        var viewer = _viewers.Single(v => v.Metadata.FileTypes.Contains(ext));
        viewer.Value.View(filename);
    }
}

Components are selected by examining the metadata associated with them. When fast lookup is required this technique is not optimal, because unless an index is built by hand, choosing a component based on metadata requires a linear search.

One of the goals of the “relationship types” approach, of which metadata is an example, is to provide a way to consume the services of an IoC container without falling back to the problematic Service Locator pattern. Requiring an O(n) lookup in the process seems unreasonable when there is a large number of components, as Service Locators can do much better.

To address this situation, Autofac provides the Autofac.Features.Indexed.IIndex<K,V> type. In Autofac 2.3 some work has been done to better integrate this into the container, so now seems like a good time to explain in more detail how it works.

Objects as Keys

For at least as long as I’ve been using them, IoC containers have supported two primary ways of looking up a component. The most common is by type:

builder.Register<Renderer>().As<IRenderer>();
// then
var r = container.Resolve<IRenderer>();

The other is by name (or by name-and-type):

builder.Register<FastRenderer>().Named<IRenderer>("Fast");
// then
var fr = container.Resolve<IRenderer>("Fast");

Resolving by name and type drives all sorts of common IoC scenarios – finding handlers for messages, controllers for routes and so-on.

Autofac stuck to this model, but down the track I realised that requiring the use of a string for the key is unnecessary. Consider the case where magic strings are eliminated elsewhere in the application in favour of an enum:

enum RenderSpeed { Slow, Fast }

Using this enum with the string-based component selection API is clunky:

builder.Register<FastRenderer>()
    .Named<IRenderer>(RenderSpeed.Fast.ToString());
// then
var fr = container.Resolve<IRenderer>(RenderSpeed.Fast.ToString());

The ToString() calls can easily be eliminated by accepting arbitrary objects, here the enum values, as keys. The above code becomes:

builder.Register<FastRenderer>()
    .Keyed<IRenderer>(RenderSpeed.Fast);
// then
var fr = container.Resolve<IRenderer>(RenderSpeed.Fast);

In many situations where components are to be selected, there’s a better key type than string, so the addition of Keyed() is one I’ve been happy with.

Looking-up Keyed Services with an Index

The examples so far use Resolve() for the purposes of illustration; there’s a better way to use keys, and that’s via IIndex<K,V>.

public interface IIndex<TKey, TValue>
{
    TValue this[TKey key] { get; }
    bool TryGetValue(TKey key, out TValue value);
}

This type is an adapter provided automatically by the container, just as the other relationship types are. It is parameterised by the type of the key and the type of the implementation.

This example is taken from a recent question about the State Pattern on StackOverflow – you can see some of the context over there.

public class Modem : IHardwareDevice
{
    IIndex<DeviceState, IDeviceState> _states;
    IDeviceState _currentState;

    public Modem(IIndex<DeviceState, IDeviceState> states)
    {
         _states = states;
         SwitchOn();
    }

    void SwitchOn()
    {
         _currentState = _states[DeviceState.Online];
    }
}

In the SwitchOn() method, the index is used to find the implementation of IDeviceState that was registered with the DeviceState.Online key.

Isn’t this a kind of Service Locator, anyway?

I was at first a little hesitant to go down this path because of the apparent similarity between looking up implementations with an index and using a Service Locator.

To cut a long story short, there’s only a superficial likeness. The important differences between this and the Service Locator approach are:

  • An index is selective, both about the kind of thing being looked up and the meaning of the key; most issues with Service Locators come from them being too broad, and I don’t think that is the case here
  • IIndex<K,V> is a subset of IDictionary<K,V> so if you’re going to go after indexes in your anti-Service-Locator rampage then you’ll have to wipe out your dictionaries, too

Still, feel free to get in there and flame me if you think this is heretical.

Why not IQueryable<T>, or ILookup<K,V>?

There’s a type in .NET 3.5 called ILookup<K,V> that could have fulfilled the role of IIndex<K,V> but unfortunately it assumes that all of the keys can be enumerated. IIndex<K,V> isn’t an enumerable type, because in order to provide that on top of Autofac’s component model, all the possible key values would need to be known by the container in advance.

IQueryable<T> is another candidate for providing optimised lookup. The essential technique would be to use it in combination with metadata, in the same way that IEnumerable<T> is used, but to build and use indexes behind the scenes to ‘smartly’ handle the expression trees corresponding to the selection predicates. Now, just to explain this is getting complicated; as attractive as this option might seem, the implementation complexity is so hideously huge by comparison that I don’t think we could ever expect it to be stable.

Conclusions

Metadata is a very flexible and elegant mechanism; it enables a much richer dependency model than keys and indexes, and supports more scenarios. Indexes and keys have their own place though, and I’d expect that if you add them to your Autofac toolbox you’ll find them useful more than once.

Simplifying ‘Configuration by Exception’

Given an assembly containing components, most of them will have similar configuration requirements. A simple assembly scanning statement usually applies to 90% of them:

Assembly componentsAssembly = // ...

var builder = new ContainerBuilder();

builder.RegisterAssemblyTypes(componentsAssembly)
    .AsImplementedInterfaces();

Now, the annoying thing is – what if one of those components needs to be scoped per-HTTP-request?

In Autofac 2.1, you could exclude it explicitly and then perform configuration separately:

builder.RegisterAssemblyTypes(componentsAssembly)
    .AsImplementedInterfaces()
    .Except<LocalCache>();

builder.RegisterType<LocalCache>()
    .As<ICache>()
    .HttpRequestScoped();

I wouldn’t say the repetition here is too bad, but over a larger assembly the separation between the Except() clause and the subsequent registration makes the code harder to follow and thus maintain.

Autofac’s scanning feature is new in version 2, and is slowly evolving towards a minimal syntax. In the latest release, version 2.2, the configuration of an excepted component can be done in-place:

builder.RegisterAssemblyTypes(componentsAssembly)
    .AsImplementedInterfaces()
    .Except<LocalCache>(cache =>
        cache.As<ICache>()
             .HttpRequestScoped();
    );

The configuration for the excepted component doesn’t inherit any of the configuration from the outer scanning operation, hence it is necessary to specify the services it will provide despite the AsImplementedInterfaces() clause in the scanning statement. While I think it would be more concise to specify only the differences between the explicitly-configured component and the rest of the scanning operation, override rules tend to bring a lot of subtle complexities with them and so they’re avoided here.

Autofac 2.2 Released

It’s that time again! There are some great features from the original plan still in the pipeline, but the completed work is important to some users so binaries for Autofac 2.2 have been made available on the Autofac site.

What’s new?

Version 2.2 is highly backwards-compatible with 2.1. Along with many small improvements, the significant additions in the new version are the return of a mutable container model, support for ASP.NET MVC 2.0 and lightweight adapters.

ContainerBuilder.Update() and full container mutability

One of the most controversial changes to Autofac in the 2.1 release was the deliberate omission of an easy way to add more components to an already-built container. The reasons for and against this are worth a blog post on their own, but in the end it turns out that integration into third-party frameworks is especially tough without this feature.

To add components to an existing container, use ContainerBuilder.Update():

var container = // something already built

var updater = new ContainerBuilder();
updater.RegisterType<A>();
updater.Register(c => new B()).As<IB>();

// Add the registrations to the container
updater.Update(container);

Configuration this way is often much harder to follow than a simple ‘register then build’ style, so again, use this feature only where necessary.

ASP.NET MVC 2.0 support

The new release is built against the ASP.NET MVC 2 binaries; you’ll have to compile from source if you want to target ASP.NET MVC 1. There can’t be many projects out there that can upgrade to Autofac 2.2, but not to the new release of ASP.NET MVC, so we expect this will be convenient for most users.

Out of the box, Autofac now supports ASP.NET MVC Areas, and integration with other ASP.NET MVC features is getting richer.

The AutofacControllerFactory policies have changed in this release, so if you previously added controllers by hand (as named services) you will need to update your code to register controllers by their concrete type (without an As() or Named() configuration clause..)

Lightweight adapters

Lightweight adapters are an easy way of expressing “for every registered X, provide an adapter of type Y.”
adapters

The introductory article is the best place to find out how this feature works.

Other changes

  • COM interfaces using No-PIA (or ‘ embedded interop types‘) can now be exposed as services
  • Simplified WCF configuration for self-hosted services
  • Scoped registration improvements: SingleInstance() now behaves as expected and binds the instance’s lifetime to the nested scope
  • Generic registration constraint checking improvements – more complex type constraints can now be handled when determining the suitability of an open generic type to satisfy a closed generic service
  • Additional Resolve()/TryResolve() convenience overloads have been added to fill some gaps
  • The same type can now be registered multiple times in a single XML configuration block
  • Several usability enhancements have been made to the scanning feature

Credits

This release, as with every Autofac release, is the product of the lively (and growing) community. There have been some especially fine patches and contributions this time around – thank you everyone for your hard work!

Lightweight Adaptation – Coming Soon

The type-to-type mapping of an IoC container obscures the fact that in reality, IoC configuration describes object graphs.

Perhaps this is why it is sometimes difficult to reason about how component instances will come together at runtime?

The problem dealt with in this article fits this description – a simple object graph that is unintuitive to build with a typical container.

Back to the Gang of Four…

The classic “Gang of Four”-style Adapter pattern ‘adapts the interface of one class to another’.
Common scenarios where adapter-like structures appear are, for example:

  • where a wrapper is needed in order to work efficiently with an underlying abstraction;
  • between different representations of the same thing, e.g. the endless variations on ILog; or,
  • between corresponding elements in different logical models

We’ll use a fairly broad definition of the pattern, in the context of an image editing application.

one-to-one

A ToolbarButton has an ICommand that is invoked when the button is clicked. ToolbarButton is an adapter for ICommand that allows the command to be invoked from the user interface.

Here we’ve attached an instance of ToolbarButton to an instance of SaveCommand, which implements ICommand. The classes are:

public interface ICommand
{
    void Execute();
}

public class SaveCommand : ICommand
{
    public void Execute()
    {
        // Save the current image
    }
}

public class ToolbarButton
{
    ICommand _command;
    public ToolbarButton(ICommand command)
    {
        _command = command;
    }
    public void Click()
    {
        _command.Execute();
    }
}

So… from an IoC perspective, what is interesting about this example?

Adapting Multiple Implementations

An application has more than one kind of command. An image editor may have Save, Open and a whole host of other commands:

PaintDotNETToolbar
But, even though all of the command implementations are the different, the widget representing them on the user interface is implemented by the same component.

To bring the example together let’s add an EditorWindow that accepts all of the toolbar buttons as an enumerable dependency.

public class EditorWindow
{
    public EditorWindow(IEnumerable<ToolbarButton> toolbarButtons)
    {
        // Left to the reader’s imagination
    }
}

Our intention here is that for each ICommand in the container, a ToolbarButton will be created to wrap it, and all of these will be passed along to the EditorWindow via the IEnumerable<T> relationship type .

These might be registered with Autofac in the following way:

var builder = new ContainerBuilder();
builder.RegisterType<SaveCommand>().As<ICommand>();
builder.RegisterType<OpenCommand>().As<ICommand>();
builder.RegisterType<ToolbarButton>();
builder.RegisterType<EditorWindow>();
using (var container = builder.Build())
{
    var window = container.Resolve<EditorWindow>();
    window.Show();
}

Yet, there is something wrong. The static structure of our code is correct, but as I lamented earlier, the object graph isn’t what we expect.

The problem is that, as far as the container is concerned, there is only one ToolbarButton component. This will be initialised with whatever happens to be the default implementation of ICommand. Autofac’s last-in-wins policy means that OpenCommand will be used as the default implementation of ICommand, and SaveCommand will be ignored.

nonadapted

This happens because the container builds object graphs top-down; first it looks for ToolbarButton, then it looks for an ICommand to satisfy its dependencies.

Registering Adapters

What we’d really like is to create multiple ToolbarButtons, each attached to a different underlying ICommand implementation.

adapters

To configure this, Autofac 2.2 essentially lets us switch the composition of ToolbarButton from top-down to bottom-up. First we find all of the ICommand implementations, and then we construct a ToolbarButton for each.

Configuration of the container is the same as before, except we change:

builder.RegisterType<ToolbarButton>();

to:

builder.RegisterAdapter<ICommand, ToolbarButton>(cmd => new ToolbarButton(cmd));

The RegisterAdapter() method takes two types as parameters: the service to adapt from, and the component type to adapt to.

Autowiring isn’t supported for the adapter component in this scenario (yet), so we include a lambda expression describing how the adapter is constructed given one of the adapted instances.

Overloads of RegisterAdapter() exist for passing in parameters and an IComponentContext from which the adapter’s other dependencies can be resolved if necessary.

Aside: @joshuamck suggested an alternative syntax that I’d also considered, along the lines of builder.RegisterType<ToolbarButton>().Adapting<ICommand>(). I think this is more in line with the intent of Autofac’s builder syntax, so depending on how the implementation goes we might see this in the 2.2 release version.

Composing with Metadata

In the example, commands can be given metadata to allow the command name to be displayed on the button.

First the commands are given names:

builder.RegisterType<SaveCommand>()
    .As<ICommand>()
    .WithMetadata("Name", "Save File");
builder.RegisterType<OpenCommand>()
    .As<ICommand>()
    .WithMetadata("Name", "Open File");

Then, the name parameter is added to the ToolbarButton constructor and the metadata is consumed:

builder.RegisterAdapter<Meta<ICommand>, ToolbarButton>(cmd =>
    new ToolbarButton(cmd.Value, (string)cmd.Metadata["Name"]));

Adapters, like other relationship types in Autofac, compose nicely with each other as the use of Meta<T> shows.

Wrapping Up*

*Excuse this terrible pun.

Lightweight adapters are a nice little helper coming in Autofac 2.2. While these scenarios don’t arise every day, when they do, container support is very convenient.

Download an example (including an Autofac 2.2 preview build) here.

Autofac 2.1 on Talking Shop Down Under

Richard Banks was kind enough to interview me on Episode 8 of Talking Shop Down Under.

If you’re interested in some of the ideas behind the new Autofac 2.1 release, be sure to check out the podcast!