简体   繁体   English

如何在Facade模式中使用依赖注入?

[英]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 解决方案尝试

  1. Properties 属性

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实现后可以更改那些属性,这不是我要支持(和调试)的东西。

  1. Aggregate interfaces 聚合接口

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类),但是很难理解这些接口组的含义。

  1. Inject a ServiceLocator that is not static in the 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 : 例如,您可以创建这样的小门面INavigationServiceILocationService

public class GeographyService : IGeographyService
{
    public GeographyService(
        INavigationService navigationService, 
        ILocationService locationService)
    { 
    }
}

The same is true for ISQLitePlatformService and DiskStorageService : ISQLitePlatformServiceDiskStorageService也是如此:

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM