我有一个服务,像这样:
@Injectable()
export class EditorService { ... }
我有一个组件,像这样:
@Component({
...
template: `<child-component></child-component>`,
providers: [EditorService],
...
})
export class SomeComponent {
constructor(
private _appleEditorService: EditorService,
private _pearEditorService: EditorService) {}
}
您可能已经注意到,此组件具有子组件:
@Component({
...
selector: 'child-component',
...
})
export class ChildComponent {
constructor(
private _appleEditorService: EditorService,
private _pearEditorService: EditorService) {}
}
如你所见,我想要两个EditorService
实例:一个用于编辑苹果,另一个用于编辑梨。但是,上面的代码不起作用,因为Angular无法知道EditorService
的哪个实例,因为它们的变量名是私有的。 _pearEditorService
中的ChildComponent
可能也指的是与_appleEditorService
中的SomeComponent
相同的例子。
问题:那么,我可以两次使用相同的Angular2服务吗?
编辑:我的问题的关键是如果可以使用相同的类。我知道有一些解决方法是为服务的每个实例创建一个单独的类,甚至通过继承实现少量代码。我只是想知道是否可以不用。
Angular DI为每个提供者维护一个实例。在您的情况下,如果您有两个具有相同类型的构造函数参数,则它们将解析为同一实例。
你可以做的是提供一个工厂功能(不同于简单的useFactory
提供商活动,虽然它也使用它)
(从https://stackoverflow.com/a/37517575/217408复制的示例)
{ provide: EditorService, useFactory:
(dep1, dep2) => {
return (x) => {
new EditorService(x, dep1, dep2);
}
}, deps: [Dep1, Dep2]
})
....
constructor(@Inject(EditorService) editorServiceFactory: any) {
let editorService1 = editorServiceFactory(1);
let editorService2 = editorServiceFactory(2);
}
如果你有一个固定数量的实例,这应该工作:
{ provide: 'instance1', useClass: EditorService },
{ provide: 'instance2', useClass: EditorService },
export class SomeComponent {
constructor(
@Inject('instance1') private _appleEditorService: EditorService,
@Inject('instance2') private _pearEditorService: EditorService) {}
}
也许重新考虑你的设计
我想你可能不得不重新考虑你的设计。有两个变量指向完全相同的EditorService有什么意义?如果他们共享相同的实现。
对此的解决方案可能是使用继承。我没有看到你的服务,所以我不确定他们做了什么,但从这段代码我假设“苹果”功能和“梨”功能实际上是不同的。然后这表明您可能有一些设计问题,而您的EditorService可能做得太多了。也许您可以将Apples和Pears类似的代码移动到名为EditorService
的服务,然后有两个类扩展它。一个AppleEditorService
and和PearEditorService
。
只是再谈谈为什么我认为您可能需要重新考虑您的设计。让我们假设appels和梨实际上具有相同的功能。所以EditorService
does也一样。您希望将一个变量用于“Apples”,将一个变量用于“Pears”。如果我看到该代码(假设其他人在您的团队中工作),并且我注意到这两个变量都指向同一个服务。 (服务是单身人士),我只是想要删除它并制作像fruitService : EditorService
or之类的东西。
无论哪种方式,你的问题都让我觉得应该改变设计。你不想要服务的两个实例,服务是单身,虽然你可以找到解决方法,但我认为这不是你问题的解决方案。
但正如我之前提到的那样。想想你的设计。你真的需要两个儿童服务,或者你能以不同的方式解决它吗?你能把苹果和梨子作为水果的子类吗?你能用一个变量'fruitService'而不是苹果/梨吗?如果您想在未来存储“草莓”,会发生什么?有一堆变量引用相同的服务(因为它们做同样的事情)但是使用不同的变量名称并不是一个好主意。想象一下在代码中看到这个
appleService = EditorService;
pearService = EditorService;
starwberryService = EditorService;
lemonService = EditorService;
...
guavaService = EditorService;
这不会表明代码有些奇怪吗?我可以想象(此时你没有提供代码)你存储了fruitInstances的数组。但是,也许一个fruitService可以工作,然后存储fruitService.store(Apple a)并将其放入一个'fruit'数组中。使用'过滤器'从阵列中获取正确的水果不应该太难。
^这只是在没有更多代码的情况下编写的。如果你编辑你的问题,有些事情可能不再适用了。
不理想,但如果您为每个组件创建一个模块,然后在每个模块上导入您的服务,您将拥有相同服务的2个实例(每个模块一个)。