【发布时间】:2018-09-25 11:12:44
【问题描述】:
我在我的 UWP 应用程序中使用 autofac。
我在后端使用facade 模式,它由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 类的构造函数没有那么多参数?
已尝试的解决方案
- 属性
我可以更改Facade 类并通过公共属性注入服务。我不喜欢很多public get / set,因为我的IFacade 合同现在表明这些属性可以在创建Facade 实现后更改,这不是我想要支持(和调试)的东西。
- 聚合接口
另一种选择是将接口聚合在一起(我称之为SomethingContext 类),但是很难理解这些接口组的含义。
- 在
Facade构造函数中注入一个非静态的ServiceLocator
最后一个似乎更可接受的解决方案(嗯……我可以接受)是使用 DI 注入非静态 ServiceLocator。这是一种解决方案2)。但是,我知道 ServiceLocator 是 frowned upon。
【问题讨论】:
-
带有构造函数注入的 DI 非常适合您真正需要的所有依赖项。我建议仅对可选依赖项使用属性注入