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