Reputation: 8382
I am using autofac
in my UWP application.
I am using the facade pattern for my backend and it is represented by an IFacade
interface.
public interface IFacade
{
/* forwards view-models' calls to different parts of the backend */
}
The view-models of my UWP application are using an implementation of IFacade
whose concrete implementation is resolved through autofac
in the UWP's App
instance.
public class App : Application
{
...
private IFacade InitializeDependencies()
{
var containerBuilder = new ContainerBuilder();
// Registers all the platform-specific implementations of services.
containerBuilder.RegisterType<LoggingService>().As<ILoggingService>().SingleInstance();
containerBuilder.RegisterType<SQLitePlatformService>().As<ISQLitePlatformService>().SingleInstance();
containerBuilder.RegisterType<DiskStorageService>().As<IDiskStorageService>().SingleInstance();
containerBuilder.RegisterType<IdentityProviderFactoryService>().As<IIdentityProviderFactoryService>().SingleInstance();
containerBuilder.RegisterType<DefaultVaultService>().As<IVaultService>().SingleInstance();
containerBuilder.RegisterType<LocationService>().As<ILocationService>().SingleInstance();
containerBuilder.RegisterType<NavigationService>().As<INavigationService>().SingleInstance();
// Registers all the dependencies of the Backend project.
var backendDependencies = new Dependencies();
backendDependencies.Setup(containerBuilder);
// Resolves the IFacade.
var container = containerBuilder.Build();
var lifetimeScope = container.BeginLifetimeScope();
return backendDependencies.ResolveFacade(lifetimeScope);
}
I have a lot of services in my backend and my implementation of IFacade
ends up with that horrific constructor referencing a lot of services' interfaces, something would make Uncle Bob cringe.
internal sealed Facade : IFacade
{
public Facade(ISessionService sessionService, IEntitiesRepository entitiesRepository, ISynchronizationService synchronizationService, IVaultService vaultService, IIdentityProviderFactoryService identityProviderFactoryService, IDemoTapeService demoTapeService, IDiskStorageService diskStorageService)
{
/* Saves the references as read-only fields. */
}
}
Question
Contrary to the ServiceLocator, using DI forces us to make all the dependencies that are needed visible. I am not sure if I am using the Dependency Injection properly.
What can I do so that my constructor of my Facade
class does not have that many parameters?
Solutions tried
I could change the Facade
class and inject the services through public properties. I am not fond of lots of public get / set
as my IFacade
contract would now indicate that those properties could be changed after the Facade
implementation is created, which is not something I want to support (and debug).
Another option would be to aggregate interfaces together (something that I call the SomethingContext
classes) but then it is harder to understand what these groups of interfaces would mean.
Facade
constructorThe last solution that seems more acceptable (well... acceptable to me) would be to use DI to inject a non-static ServiceLocator. It is kind of solution 2). However, I know the ServiceLocator is something that is frowned upon.
Upvotes: 4
Views: 4239
Reputation: 2898
So one another approach is to create some smaller Facade Services and then inject those services to the main facade.
For example you can create such smaller facade for INavigationService
and ILocationService
:
public class GeographyService : IGeographyService
{
public GeographyService(
INavigationService navigationService,
ILocationService locationService)
{
}
}
The same is true for ISQLitePlatformService
and DiskStorageService
:
public class StorageService : IStorageService
{
public StorageService(
ISQLitePlatformService databaseService,
DiskStorageService diskStorageService)
{
}
}
That's of course only an example of an idea.
Such an approach is generally considered better than aggregate services with all the dependencies aggregated (http://autofaccn.readthedocs.io/en/latest/advanced/aggregate-services.html) or ServiceLocator (anti-)pattern. You can also read some thoughts about it here: http://blog.ploeh.dk/2010/02/02/RefactoringtoAggregateServices/
Upvotes: 3