Dependency Injection and Class Inheritance

Once upon a project there was a base class:

class abstract CommonLogic
{
    protected CommonLogic(IFirstLowLevelService firstService) {}
}

…that several developers wanted to subclass. They all believed in the inversion of control principle and took therefore all their dependencies as constructor parameters.  With Autofac, a dependency injection framework at hand they ventured forth implementing many great subclasses. Some of these appeared like this:

class SpecificLogic : CommonLogic
{
    public SpecificLogic(
        IHighLevelService highLevelService,
        IFirstLowLevelService firstService)
    : base(firstService) {}
}

All was well and the number of variations of special logic classes grew and prospered.

Until one day a Senior Developer wanted to extend the base class with new logic requiring more dependencies. Now all the subclasses had to include the new dependencies in their constructors too, passing them on to the base class.

class abstract CommonLogic
{
    protected CommonLogic(
        IFirstLowLevelService firstService,
        ISecondLowLevelService secondService,
        IThirdLowLevelService thirdService
        ) {}
}

class SpecificLogic : CommonLogic
{
    public SpecificLogic(
        IHighLevelService highLevelService,
        IFirstLowLevelService firstService
        ISecondLowLevelService secondService,
        IThirdLowLevelService thirdService)
    : base(firstService, secondService, thirdService) {}
}

The changes caused great disturbance throughout the Source Repository, affecting both production code and test code alike, delaying schedules and disheartening the developers.

Then a brave developer set out on a quest to free the Source from darkness. And he found the Aggregate Service, a pattern that promised to isolate the subclasses from future changes in the base class constructor:

class abstract CommonLogic
{
    public interface IAggregateService
    {
        IFirstLowLevelService FirstService {get;}
        ISecondLowLevelService SecondService {get;}
        IThirdLowLevelService ThirdService {get;}
    }

    protected CommonLogic(IAggregateService aggregateService) {}
}

class SpecificLogic : CommonLogic
{
    public SpecificLogic(
        IHighLevelService highLevelService,
        IAggregateService aggregateService)
    : base(aggregateService) {}
}

Furthermore, by tapping into the power of Castle DynamicProxy2, the developer crafted a device that could dynamically generate aggregate services, completely removing the burden of implementing classes for each aggregate service interface.

Finally, the valiant adventurer approached the Senior Developer and presented the pattern and how it could free them from distress merely by aggregating constructor-injected dependencies into one dependency. Seeing its brilliance, the aggregate service pattern was implemented throughout the Source spreading light and joy to the team. Changes could now be made to the base class dependencies by merely changing the IAggregateService interface, and no change would have to be done to the subclasses ever again.

So great was the joy and relief that the Senior Developer declared:

The Aggregate Service belongs to all developers of the land and shall thus be contributed to Autofac.

Share

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();
builder.Register<CustomerService>();
builder.RegisterGeneratedFactory<CustomerServiceFactory>();
builder.Register<CustomerController>();

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();
builder.Register<CustomerService>().As();
builder
  .RegisterGeneratedFactoryFromOpenType(typeof(ServiceFactory<>));
builder.Register<CustomerController>();

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
    RegisterGeneratedFactoryFromOpenType
    (this ContainerBuilder builder, Type openFactoryType)
{
    return builder.RegisterGeneric(openFactoryType)
        .OnPreparing(Prepare);
}

static void Prepare(object sender, PreparingEventArgs args)
{
    var factoryType = args.Component
        .Descriptor.BestKnownImplementationType;
    var serviceType = factoryType
        .GetMethod("Invoke").ReturnType; 

    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.

Share