Tamir Dresher

Using Autofac Aggregate Services

13 Sep 2016

This post was originally published on 13 Sep 2016 at http://blogs.microsoft.co.il/iblogger/2016/09/13/using-autofac-aggregate-services/

I really like using Autofac, it’s one of the most productive libraries I know, and it’s so much fun to discover new features.

Aggregate Services is Autofac feature that allows you to wrap a set of dependencies into a single aggregate without the need to implement a concrete type for it.

Consider the following case where you have a base class that has dependencies on a few other services, and two derived classes:

1
2
3
4
5
6
7
8
9
10
11
12
13
class BaseLicenseGenerator:ILicenseGenerator
{
    //members
 
    public BaseLicenseGenerator(ILogger logger, IUserRepository userRepository, ILicenseRepository licenseRepository)
    {
        _logger = logger;
        _userRepository = userRepository;
        _licenseRepository = licenseRepository;
    }
         
    //...
}

1
2
3
4
5
6
7
8
9
10
class PerMonthLicenseGenerator
    : BaseLicenseGenerator
{
    public PerMonthLicenseGenerator(ILogger logger, IUserRepository userRepository, ILicenseRepository licenseRepository)
        : base(logger, userRepository, licenseRepository)
    {
    }
 
    //...
}

1
2
3
4
5
6
7
8
9
class YearlyLicenseGenerator : BaseLicenseGenerator
{
    public YearlyLicenseGenerator(ILogger logger, IUserRepository userRepository, ILicenseRepository licenseRepository)
        : base(logger, userRepository, licenseRepository)
    {
    }
 
    //...
}

 

To me, the need to include all the dependencies of the base class inside the derived classes constructor is a little counter-productive. If I need to make a change to the dependencies of the base class, I’ll have to go and modify the derived classes as well.

With Autofac Aggregate Services, I can change the base class to include a single dependency which will wrap all the other dependencies together.
All I need is to add reference to the Autofac.Extras.AggregateService nuget package.

1
2
3
4
5
6
public interface ILicenseGeneratorDependencies
{
    ILogger Logger { get; }
    IUserRepository UserRepository { get; }
    ILicenseRepository LicenseRepository { get; }
}

Now I just need to register this interface to my container as an aggregate service and change my classes to use it.

1
2
3
4
5
6
7
var containerBuilder = new ContainerBuilder();
containerBuilder.RegisterType().As();
containerBuilder.RegisterType().As();
containerBuilder.RegisterType().As();
containerBuilder.RegisterType().AsSelf();
 
containerBuilder.RegisterAggregateService();

1
2
3
4
5
6
7
8
9
10
11
12
13
class BaseLicenseGenerator : ILicenseGenerator
{
    //members
     
    public BaseLicenseGenerator(ILicenseGeneratorDependencies licenseGeneratorDependencies)
    {
        _logger = licenseGeneratorDependencies.Logger;
        _userRepository = licenseGeneratorDependencies.UserRepository;
        _licenseRepository = licenseGeneratorDependencies.LicenseRepository;
    }
     
    //...
}

1
2
3
4
5
6
7
8
9
10
class PerMonthLicenseGenerator
    : BaseLicenseGenerator
{
    public PerMonthLicenseGenerator(ILicenseGeneratorDependencies licenseGeneratorDependencies)
        : base(licenseGeneratorDependencies)
    {
    }
 
    //...
}

 

that’s it! now if I need to change the BaseLicenseGenerator class and add a dependency, I just need to change the ILicenseGeneratorDependencies interface, and leave the derived classes untouched