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

时间:2018-04-15 17:48:03

标签: c# .net uwp autofac

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

我在后端使用facade模式,它由IFacade接口表示。

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

我的UWP应用程序的视图模型使用IFacade的实现,其具体实现通过UWP autofac实例中的App解决。

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. 属性
  2. 我可以更改Facade类并通过公共属性注入服务。我不喜欢很多public get / set,因为我的IFacade合同现在表明在创建Facade实现后可以更改这些属性,这不是我想支持的(和调试)。

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

      1. Facade构造函数
      2. 中注入非静态的ServiceLocator

        最后一个看起来更容易接受的解决方案(好吧......我可以接受)就是使用DI注入一个非静态的ServiceLocator。这是一种解决方案2)。但是,我知道ServiceLocator是frowned upon

1 个答案:

答案 0 :(得分:1)

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

例如,您可以为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/