Generate generic factories with Autofac

With Autofac, factory delegates can be generated based on delegate signatures. This article shows how this is done and also shows a solution to using generic delegates with Autofac.

One of the features I like the most in Autofac is the ability to register a factory in the container. A factory in this context is “some method that knows how to build and return an instance of some type”.

Factories are useful when you need fine-grained control over when dependencies should be resolved. Also, if you have dependencies that requires data input (e.g. a constructor parameter) and you need some way of passing that data into the dependency, a factory is your friend.

With Autofac it gets even better. Using C# I can declare a delegate that represents the signature of such a factory, register the delegate in my container and voila! Autofac generates the implementation based on the signature.

So I could declare a delegate like this:

public delegate ICustomerService CustomerServiceFactory();

and have it injected in, say, one of my controller classes, like this:

public class CustomerController
    private CustomerServiceFactory _customerServiceFactory;
    public CustomerController(CustomerServiceFactory customerServiceFactory)
        _customerServiceFactory = customerServiceFactory;

My controller now have the ability to decide when to create the service instance and still not need to know how.

To make the sample complete (thus far) I’ll show how the Autofac container setup looks like at this point:

var builder = new ContainerBuilder();

This works great. And was fairly easy too don’t think? Now imagine that these classes and delegates was a small part of a real system, with hundreds of controllers and services. Having to declare a factory delegate for each service becomes a pain, let aside registering them in the container.

Wouldn’t it be nice if we could declare only one factory that could build all service types? Turns out you can. Think about the following generic delegate:

public delegate T ServiceFactory<T>() where T:class;

Our updated controller dependency now looks like this:

public class CustomerController
    private ServiceFactory<CustomerService> _customerServiceFactory;
    public CustomerController
        (ServiceFactory<CustomerService> customerServiceFactory)
        _customerServiceFactory = customerServiceFactory;

Registering such a delegate in the container becomes a bit tricky, since we don’t know T at registration time. Even more so, we cannot generate the factory delegate at registration time! The solution is to register the open generic type coupled with a method that will generate the factory when the dependency is asked for. The Autofac setup should now look like this:

var builder = new ContainerBuilder();

The RegisterGeneratedFactoryFromOpenType extension method does two things:

  1. Register the open generic type using builder.RegisterGeneric
  2. Attach factory generation code to the OnPreparing event.

The OnPreparing event will be fired when Autofac tries to resolve a closed version of the delegate, in our case the ServiceFactory delegate. Since the event argument contains this type we have everything necessary for generating the factory implementation. And here’s the implementation of RegisterGeneratedFactoryFromOpenType:

public static IGenericRegistrar
    (this ContainerBuilder builder, Type openFactoryType)
    return builder.RegisterGeneric(openFactoryType)

static void Prepare(object sender, PreparingEventArgs args)
    var factoryType = args.Component
    var serviceType = factoryType

    var service = new TypedService(serviceType);
    var factory = new FactoryGenerator(factoryType, service); 

    args.Instance = factory
        .GenerateFactory(args.Context, args.Parameters);

Note: this code is based on the latest release of Autofac 1.


Author: Peter

Hi, my name is Peter Lillevold. I currently live with my two kids in eastern Norway in a small town called Askim. This blog is an outlet for technical articles on software development endavours. Thanks for stopping by, hope you find something useful!

3 thoughts on “Generate generic factories with Autofac”

  1. Good post. I think
    public delegate T ServiceFactory() where T:class;

    is supposed to be
    public delegate T ServiceFactory() where T:class;

    Have you looked at the performance impact of this approach. Does Autofac do something similar under the hood?

  2. Hey, @blu , thanks for pointing this out. Man, I fixed it for some of the other sample parts but failed to spot the generic delegate!

    Well, performance wise this approach is equal to registering non-generic delegates. The difference is with non-generics, the delegate is generated at register time. With generics, the delegate is generated at resolve time.

    Either way, the delegate will only have to be generated once. Next time the delegate is asked for, it will already be available in the container.

Comments are closed.