Angular2: Como usar várias instâncias do mesmo serviço?

Eu tenho um serviço como este

@Injectable() export class EditorService { ... } 

E eu tenho um componente, como este

 @Component({ ... template: ``, providers: [EditorService], ... }) export class SomeComponent { constructor( private _appleEditorService: EditorService, private _pearEditorService: EditorService) {} } 

Como você deve ter notado, este componente tem um componente filho:

 @Component({ ... selector: 'child-component', ... }) export class ChildComponent { constructor( private _appleEditorService: EditorService, private _pearEditorService: EditorService) {} } 

Como você pode ver, eu quero duas instâncias do meu EditorService, uma será usada para editar maçãs e outra para editar peras. No entanto, o código acima não funcionará, pois não há como o Angular saber qual instância do EditorService é qual, como seus nomes de variables ​​são privados. _pearEditorService em ChildComponent pode estar se referindo à mesma instância de _appleEditorService em SomeComponent .

Pergunta: Como então, posso usar o mesmo serviço Angular2 duas vezes? EDIT: O ponto da minha pergunta é se é possível usar a mesma class. Eu sei que existem soluções alternativas criando uma class separada para cada instância do serviço, e até mesmo fazendo isso com pouco código por inheritance. Eu só quero saber se isso pode ser feito sem.

DI angular mantém uma única instância por provedor. No seu caso, se você tiver dois parâmetros de construtor com o mesmo tipo, eles serão resolvidos para a mesma instância.

O que você pode fazer é fornecer uma function de fábrica (diferente de um evento provedor useFactory simples, embora ele também o use)

(Exemplo copiado de 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); } 

Se você tiver um número fixo de instâncias, isso deve funcionar:

 { provide: 'instance1', useClass: EditorService }, { provide: 'instance2', useClass: EditorService }, 
 export class SomeComponent { constructor( @Inject('instance1') private _appleEditorService: EditorService, @Inject('instance2')private _pearEditorService: EditorService) {} } 

talvez repensar seu design

Eu acho que você pode ter que repensar seu design completamente então. Qual é o ponto de ter duas variables ​​que apontam exatamente para o mesmo EditorService? Se eles compartilham a mesma implementação.

Solução de inheritance

Uma solução para isso seria, talvez, usar Herança . Eu não vi seus serviços, então eu não tenho certeza do que eles fazem, mas a partir deste código eu estou supondo que a funcionalidade “apple” e a funcionalidade “pêra” são realmente diferentes. Então isso indica que você pode ter alguns problemas de design e seu EditorService pode estar fazendo muito. Talvez você possa mover o código que é semelhante para Maçãs e Peras para um serviço chamado EditorService e, em seguida, ter duas classs para estender isso. um AppleEditorService e um PearEditorService .

Use fruitService geral

Só para falar um pouco mais sobre porque eu acho que você talvez precise repensar seu design. Vamos supor que os appels e pears realmente tenham a mesma funcionalidade. Então, o EditorService faz o mesmo. Você quer que uma variável seja usada para ‘Maçãs’ e outra para ‘Peras’. Se eu vir esse código (suponha que outras pessoas trabalhem em sua equipe), e noto que ambas as variables ​​apontam para o mesmo serviço. (Serviços são singletons), eu seria apenas tentado a remover isso e fazer algo como fruitService : EditorService ou algo parecido.

De qualquer forma, sua pergunta me faz pensar que o design deve ser alterado. Você não quer duas instâncias do serviço, os serviços são singleton e, embora você possa encontrar maneiras de contornar isso, não acho que seja realmente a solução para o seu problema.


Mas como eu mencionei antes. Pense no seu design. Você realmente precisa de dois serviços infantis ou pode resolvê-lo de forma diferente? Você pode ter maçãs e peras apenas subclass frutas? Você pode usar apenas uma variável ‘fruitService’ em vez de ambas as maçãs / peras? O que acontece quando você quer armazenar “Morangos” também no futuro? Ter um monte de variables ​​referem-se ao mesmo serviço (porque fazem a mesma coisa), mas com nomes de variables ​​diferentes não é uma boa ideia. Imagine ver isso no código

  appleService = EditorService; pearService = EditorService; starwberryService = EditorService; lemonService = EditorService; ... guavaService = EditorService; 

Isso não indica que algo é estranho com o código? Eu posso imaginar (você não forneceu o código neste ponto) que você armazena uma matriz das frutas. Mas então talvez um serviço de frutas poderia funcionar e, em seguida, armazenar fruitService.store (Apple a) e colocar isso em uma matriz de ‘frutas’. Use um “filtro” para obter o fruto certo da matriz não deve ser muito difícil.

^ Isso é apenas escrito sem ter mais do seu código para continuar. Se você editar sua pergunta, algumas coisas podem não aguentar mais.