繁体   English   中英

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

[英]How to use Dependency Injection with the Facade pattern?

我在UWP应用程序中使用了autofac

我正在为我的后端使用外观模式,它由IFacade接口表示。

public interface IFacade 
{
    /* forwards view-models' calls to different parts of the backend */
}

我的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);
    }

我的后端有很多服务,而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. */
    }
}

与ServiceLocator相反,使用DI迫使我们使所有需要的依赖项可见。 我不确定我是否正确使用了依赖注入。

我该怎么办,以使我的Facade类的构造函数没有那么多参数?

解决方案尝试

  1. 属性

我可以更改Facade类,并通过公共财产注入服务。 我不喜欢很多public get / set因为我的IFacade合同现在表明在创建Facade实现后可以更改那些属性,这不是我要支持(和调试)的东西。

  1. 聚合接口

另一个选择是将接口聚合在一起(我称之为SomethingContext类),但是很难理解这些接口组的含义。

  1. 注入在Facade构造函数中不是静态的ServiceLocator

似乎更可接受(对我来说可以接受)的最后一个解决方案是使用DI注入非静态ServiceLocator。 这是一种解决方案2)。 但是,我知道的服务定位是什么,是令人难以接受的

因此,另一种方法是创建一些较小的外观服务,然后将这些服务注入主外观。

例如,您可以创建这样的小门面INavigationServiceILocationService

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

ISQLitePlatformServiceDiskStorageService也是如此:

public class StorageService : IStorageService 
{
    public StorageService(
        ISQLitePlatformService databaseService, 
        DiskStorageService diskStorageService)
    { 
    }
}

当然,这只是一个想法的例子。

通常认为这种方法比聚合所有依赖项( http://autofaccn.readthedocs.io/en/latest/advanced/aggregate-services.html )或ServiceLocator(反)模式的聚合服务更好。 您还可以在此处阅读有关此内容的一些想法: http : //blog.ploeh.dk/2010/02/02/RefactoringtoAggregateServices/

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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