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