ServiceScope class
O padrão do localizador de serviço utilizado pelo Estrutura do SharePoint.
Comentários
O ServiceScope proporciona uma maneira formal para os componentes registrarem e consumirem dependências ("serviços") e habilitar implementações diferentes para serem registradas em diferentes escopos. Isso melhora a modularidade por meio da separação de componentes de suas dependências de forma extensível.
Por exemplo, suponha que vários componentes precisem ter acesso a uma instância do PageManager. Poderíamos simplesmente tornar o PageManager único (ou seja, variável global), mas isso não funcionará, por exemplo, se for necessário criar uma caixa de diálogo pop-up que exija uma segunda instância do PageManager. Uma solução melhor seria adicionar o PageManager como um parâmetro de construtor para cada componente que precise dele; no entanto, em seguida, encontramos imediatamente o problema que qualquer código que chame esses construtores também precisam de um parâmetro PageManager. Numa aplicação com muitas dessas dependências, a lógica de negócio que une muitos subsistemas acabaria por recolher um parâmetro de construtor para todas as dependências possíveis, o que é estranho. Uma solução natural seria mover todas as dependências para uma classe com nome como "ApplicationContext" e, em seguida, utilizar como nosso parâmetro de construtor. Isso permite que o PageManager seja passado para classes que precisam dele sem encher as classes intermediárias que não precisam. No entanto, ainda há um problema de design que "ApplicationContext" tem dependências embutidas em muitas coisas não relacionadas. É uma abordagem mais flexível para torná-lo um dicionário que pode pesquisar itens para os consumidores/provedores que saibam a chave de pesquisa certa (ou seja, ServiceKey). Este é o padrão de design de "localizador de serviço" popular, familiar da API SPContext no SharePoint clássico.
O ServiceScope leva esta ideia mais longe de duas formas importantes: em primeiro lugar, fornece um mecanismo de âmbito para que, por exemplo, se tivermos duas páginas diferentes, cada uma delas possa fornecer uma instância pageManager exclusiva enquanto partilha outras dependências comuns. Em segundo lugar, ele permite que um ServiceKey forneça uma implementação padrão da dependência. Isso é importante para a estabilidade da API em nosso ambiente modular do lado do cliente: Por exemplo, suponha que a versão 2.0 do nosso aplicativo introduziu uma nova interface do IDiagnosticTracing que um componente de versão 2.0 espera consumir. Se o componente de versão 2.0 for carregado por um aplicativo 1.0 mais antigo, ele falhará. Nós podemos corrigir isso exigindo que cada consumidor verifique se há dependências faltando e administrar esse caso, mas isso exigiria muitas verificações. Uma solução melhor é garantir que existe sempre uma implementação predefinida, talvez apenas um comportamento trivial, para que os componentes possam assumir que consume() devolverá sempre algum objeto que implemente o contrato.
Uso: As instâncias de ServiceScope são criadas chamando ServiceScope.startNewRoot() ou ServiceScope.startNewChild(). Estão inicialmente num estado "inacabado", durante o qual provide() pode ser chamado para registar chaves de serviço, mas consume() não é permitido. Depois de ServiceScope.finish() ser chamado, consume() é permitido e provide() é agora não permitido. Essa semântica garante que ServiceScope.consume() sempre retorne o mesmo resultado para a mesma chave e não dependa da ordem de inicialização. Também nos permite suportar dependências circulares sem nos preocuparmos com ciclos infinitos. (As dependências circulares são melhor evitadas, no entanto, isto é difícil de garantir ao trabalhar com componentes que foram contribuídos por vários terceiros sem qualquer coordenação.) Para evitar erros, é melhor chamar sempre consume() dentro de uma chamada de retorno de serviceScope.whenFinished().
Construtores
(constructor)(parent) | Constrói uma nova instância da |
Métodos
consume(service |
Consome um serviço do âmbito do serviço. |
create |
Esta é uma função abreviada equivalente à construção de uma nova instância do simpleServiceClass e, em seguida, ao registá-la ao chamar ServiceScope.provide(). |
create |
Essa é uma função abreviada que constrói a implementação padrão do ServiceKey especificado e registra-o chamando ServiceScope.provide(). |
finish() | Conclui a sequência de inicialização de um âmbito de serviço. |
get |
Retorna o pai do ServiceScope atual ou indefinido se este for um escopo de raiz. |
provide(service |
Adicionar um novo serviço a um âmbito de serviço. |
start |
Cria um novo ServiceScope que é um filho do escopo atual. |
start |
Crie um novo ServiceScope de nível raiz. Somente os escopos de nível raiz têm a capacidade de criar automaticamente implementações padrão de ServiceKeys. |
when |
Adie uma operação até que ServiceScope.finish() esteja concluído. |
Detalhes do construtor
(constructor)(parent)
Constrói uma nova instância da ServiceScope
classe
protected constructor(parent: ServiceScope | undefined);
Parâmetros
- parent
-
ServiceScope | undefined
Detalhes do método
consume(serviceKey)
Consome um serviço do âmbito do serviço.
consume<T>(serviceKey: ServiceKey<T>): T;
Parâmetros
- serviceKey
-
ServiceKey<T>
a chave que foi usada quando provide() foi chamado para registrar o serviço
Retornos
T
a instância do serviço
Comentários
Os componentes devem chamar esta função para "consumir" uma dependência, ou seja, procurar o serviceKey e retornar a instância do serviço registrado. Se não for possível localizar a instância, será automaticamente criada e registada uma instância predefinida com o ServiceScope de raiz.
createAndProvide(serviceKey, simpleServiceClass)
Esta é uma função abreviada equivalente à construção de uma nova instância do simpleServiceClass e, em seguida, ao registá-la ao chamar ServiceScope.provide().
createAndProvide<T>(serviceKey: ServiceKey<T>, simpleServiceClass: {
new (serviceScope: ServiceScope): T;
}): T;
Parâmetros
- serviceKey
-
ServiceKey<T>
a chave que pode ser usada posteriormente para consumir o serviço
- simpleServiceClass
-
{ new (serviceScope: ServiceScope): T; }
a classe TypeScript a ser construída
Retornos
T
uma instância de simpleServiceClass construída recentemente
createDefaultAndProvide(serviceKey)
Essa é uma função abreviada que constrói a implementação padrão do ServiceKey especificado e registra-o chamando ServiceScope.provide().
createDefaultAndProvide<T>(serviceKey: ServiceKey<T>): T;
Parâmetros
- serviceKey
-
ServiceKey<T>
a chave que pode ser usada posteriormente para consumir o serviço
Retornos
T
uma instância do serviço que foi construída usando ServiceKey.defaultCreator
finish()
Conclui a sequência de inicialização de um âmbito de serviço.
finish(): void;
Retornos
void
Comentários
Quando um ServiceScope é iniciado pela primeira vez, está num estado "inacabado" em que provide() é permitido, mas consume() não é permitido. Depois de efetuar a chamada finish(), consume() é permitido, mas provide() não é permitido.
Este formalismo impede uma série de situações complexas que podem levar a erros. Por exemplo, supõe-se que Scope2 é um subordinado do Âmbito1 e o Âmbito1 fornece a instância A1 da interface A. Se alguém consumir A1 a partir do Âmbito2 (através da herança) antes de Scope2.provide() ser chamado com A2, uma chamada subsequente para Scope2.consume() poderá devolver um resultado diferente da chamada anterior. Este não-administrador pode causar resultados imprevisíveis difíceis de diagnosticar.
getParent()
Retorna o pai do ServiceScope atual ou indefinido se este for um escopo de raiz.
getParent(): ServiceScope | undefined;
Retornos
ServiceScope | undefined
o escopo do serviço pai
provide(serviceKey, service)
Adicionar um novo serviço a um âmbito de serviço.
provide<T>(serviceKey: ServiceKey<T>, service: T): T;
Parâmetros
- serviceKey
-
ServiceKey<T>
a chave que será usada mais tarde para consumir o serviço
- service
-
T
a instância do serviço que está sendo registrada
Retornos
T
o mesmo objeto que foi passado como o parâmetro "service"
Comentários
ServiceScope.provide() é utilizado para registar uma implementação da serviceKey especificada para o âmbito atual e uma implementação de um determinado rootServiceKey para o âmbito de raiz. Só pode ser usado quando o ServiceScope estiver em um estado "não concluído", ou seja, antes de finish() ter sido chamado.
startNewChild()
Cria um novo ServiceScope que é um filho do escopo atual.
startNewChild(): ServiceScope;
Retornos
o ServiceScope raiz recém-criado
Comentários
Os âmbitos de serviço formam uma estrutura de árvore, de modo que, ao consumir um serviço, se a chave não for explicitamente fornecida por um âmbito subordinado, a hierarquia principal será consultada.
startNewRoot()
Crie um novo ServiceScope de nível raiz. Somente os escopos de nível raiz têm a capacidade de criar automaticamente implementações padrão de ServiceKeys.
static startNewRoot(): ServiceScope;
Retornos
o ServiceScope raiz recém-criado
whenFinished(callback)
Adie uma operação até que ServiceScope.finish() esteja concluído.
whenFinished(callback: () => void): void;
Parâmetros
- callback
-
() => void
Um bloco de código que precisa chamar ServiceScope.consume()
Retornos
void
Comentários
É um erro para chamar ServiceScope.consume() antes de ter chamado finish(). A maneira mais confiável para proteger seu componente contra esse erro é executar as chamadas consume() dentro de um retorno de chamada whenFinished(). Se o escopo do serviço já estiver concluído, o retorno de chamada será executado imediatamente; caso contrário, ele será executado posteriormente quando o escopo tiver sido concluído.
NOTA: esta não é uma chamada de retorno assíncrona. Normalmente, a inicialização do ServiceScope é barata e de curta duração. No entanto, o fluxo de controlo costuma passar por vários construtores e classes base, que podem ser simplificados com whenFinished().