[英]How to use Dependency Injection with the Facade pattern?
I am using autofac
in my UWP application. 我在UWP应用程序中使用了autofac
。
I am using the facade pattern for my backend and it is represented by an IFacade
interface. 我正在为我的后端使用外观模式,它由IFacade
接口表示。
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. 我的UWP应用程序的视图模型使用IFacade
的实现,其具体实现通过UWP的App
实例中的autofac
进行解析。
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. 我的后端有很多服务,而IFacade
实现最终以引用许多服务接口的可怕构造函数结尾,这会使Bob叔叔畏缩。
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. 与ServiceLocator相反,使用DI迫使我们使所有需要的依赖项可见。 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? 我该怎么办,以使我的Facade
类的构造函数没有那么多参数?
Solutions tried 解决方案尝试
I could change the Facade
class and inject the services through public properties. 我可以更改Facade
类,并通过公共财产注入服务。 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). 我不喜欢很多public get / set
因为我的IFacade
合同现在表明在创建Facade
实现后可以更改那些属性,这不是我要支持(和调试)的东西。
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. 另一个选择是将接口聚合在一起(我称之为SomethingContext
类),但是很难理解这些接口组的含义。
Facade
constructor 注入在Facade
构造函数中不是静态的ServiceLocator The last solution that seems more acceptable (well... acceptable to me) would be to use DI to inject a non-static ServiceLocator. 似乎更可接受(对我来说可以接受)的最后一个解决方案是使用DI注入非静态ServiceLocator。 It is kind of solution 2). 这是一种解决方案2)。 However, I know the ServiceLocator is something that is frowned upon . 但是,我知道的服务定位是什么,是令人难以接受的 。
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
: 例如,您可以创建这样的小门面INavigationService
和ILocationService
:
public class GeographyService : IGeographyService
{
public GeographyService(
INavigationService navigationService,
ILocationService locationService)
{
}
}
The same is true for ISQLitePlatformService
and DiskStorageService
: ISQLitePlatformService
和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. 通常认为这种方法比聚合所有依赖项( http://autofaccn.readthedocs.io/en/latest/advanced/aggregate-services.html )或ServiceLocator(反)模式的聚合服务更好。 You can also read some thoughts about it here: http://blog.ploeh.dk/2010/02/02/RefactoringtoAggregateServices/ 您还可以在此处阅读有关此内容的一些想法: http : //blog.ploeh.dk/2010/02/02/RefactoringtoAggregateServices/
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.