Partager via


ServiceScope class

Modèle de localisateur de service utilisé par le SharePoint Framework.

Remarques

ServiceScope fournit un moyen formalisé pour les composants d’inscrire et de consommer des dépendances (« services ») et de permettre l’inscription de différentes implémentations dans différentes étendues. Cela améliore la modularité en découpant les composants de leurs dépendances de manière extensible.

Par exemple, supposons que différents composants doivent accéder à un instance IPageManager. Nous pourrions simplement faire du PageManager un singleton (c’est-à-dire une variable globale), mais cela ne fonctionnera pas, par exemple, si nous devons créer une boîte de dialogue contextuelle qui nécessite une deuxième instance PageManager. Une meilleure solution consiste à ajouter le PageManager en tant que paramètre de constructeur pour chaque composant qui en a besoin. Toutefois, nous sommes immédiatement confrontés au problème que tout code qui appelle ces constructeurs a également besoin d’un paramètre PageManager. Dans une application avec de nombreuses dépendances de ce type, la logique métier qui lie de nombreux sous-systèmes finirait par récupérer un paramètre de constructeur pour chaque dépendance possible, ce qui est maladroit. Une solution naturelle consiste à déplacer toutes les dépendances dans une classe nommée « ApplicationContext », puis à la transmettre en tant que paramètre de constructeur. Cela permet de passer le PageManager aux classes qui en ont besoin sans encombrer les classes intermédiaires qui n’en ont pas. Toutefois, il existe toujours un problème de conception lié au fait que « ApplicationContext » a des dépendances codées en dur sur de nombreux éléments non liés. Une approche plus flexible consiste à en faire un dictionnaire capable de rechercher des éléments pour les consommateurs/fournisseurs qui connaissent la clé de recherche appropriée (par exemple, ServiceKey). Il s’agit du modèle de conception populaire de « localisateur de services », familier de l’API SPContext dans SharePoint classique.

ServiceScope approfondit cette idée de deux manières importantes : tout d’abord, il fournit un mécanisme d’étendue qui, par exemple, si nous avons deux pages différentes, elles peuvent chacune fournir un instance PageManager unique tout en partageant d’autres dépendances communes. Deuxièmement, elle permet à servicekey de fournir une implémentation par défaut de la dépendance. Ceci est important pour la stabilité de l’API dans notre environnement modulaire côté client : par exemple, supposons que la version 2.0 de notre application introduise une nouvelle interface IDiagnosticTracing qu’un composant de la version 2.0 s’attend à consommer. Si le composant version 2.0 est chargé par une ancienne application 1.0, il échoue. Nous pourrions résoudre ce problème en demandant à chaque consommateur de case activée pour toutes les dépendances manquantes et de gérer ce cas, mais cela nécessiterait de nombreuses vérifications. Une meilleure solution consiste à s’assurer qu’une implémentation par défaut existe toujours, peut-être simplement un comportement trivial, afin que les composants puissent supposer que consume() retourne toujours un objet qui implémente le contrat.

Utilisation : les instances ServiceScope sont créées en appelant ServiceScope.startNewRoot() ou ServiceScope.startNewChild(). Ils sont initialement dans un état « inachevé », pendant lequel provide() peut être appelé pour inscrire des clés de service, mais consume() n’est pas autorisé. Une fois ServiceScope.finish() appelé, consume() est autorisé et provide() est désormais interdit. Ces sémantiques garantissent que ServiceScope.consume() retourne toujours le même résultat pour la même clé et ne dépend pas de l’ordre d’initialisation. Il nous permet également de prendre en charge les dépendances circulaires sans nous soucier des boucles infinies. (Il est préférable d’éviter les dépendances circulaires, mais cela est difficile à garantir lorsque vous travaillez avec des composants qui ont été fournis par divers tiers sans aucune coordination.) Pour éviter les erreurs, il est préférable d’appeler toujours consume() à l’intérieur d’un rappel à partir de serviceScope.whenFinished().

Constructeurs

(constructor)(parent)

Construit une nouvelle instance de la ServiceScope classe

Méthodes

consume(serviceKey)

Consomme un service à partir de l’étendue du service.

createAndProvide(serviceKey, simpleServiceClass)

Il s’agit d’une fonction abrégée qui équivaut à construire une nouvelle instance du simpleServiceClass, puis à l’inscrire en appelant ServiceScope.provide().

createDefaultAndProvide(serviceKey)

Il s’agit d’une fonction de raccourci qui construit l’implémentation par défaut du serviceKey spécifié, puis l’enregistre en appelant ServiceScope.provide().

finish()

Termine la séquence d’initialisation pour une étendue de service.

getParent()

Renvoie le parent du ServiceScope actuel ou « Undefined » s’il s’agit d’une étendue racine.

provide(serviceKey, service)

Ajouter un nouveau service à une étendue de service.

startNewChild()

Construit un nouveau ServiceScope qui est un enfant de l’étendue actuelle.

startNewRoot()

Créez un nouveau ServiceScope de niveau racine. Seules les étendues de niveau racine peuvent créer automatiquement des implémentations par défaut de ServiceKeys.

whenFinished(callback)

Différer une opération jusqu’à ce que ServiceScope.finish() soit terminé.

Détails du constructeur

(constructor)(parent)

Construit une nouvelle instance de la ServiceScope classe

protected constructor(parent: ServiceScope | undefined);

Paramètres

parent

ServiceScope | undefined

Détails de la méthode

consume(serviceKey)

Consomme un service à partir de l’étendue du service.

consume<T>(serviceKey: ServiceKey<T>): T;

Paramètres

serviceKey

ServiceKey<T>

clé que vous avez utilisée lorsque provide() a été appelé pour enregistrer le service

Retours

T

l’instance de service

Remarques

Les composants doivent appeler cette fonction pour « consommer » une dépendance, par exemple, rechercher serviceKey et retourner l’instance du service enregistré. Si le instance est introuvable, une instance par défaut est automatiquement créée et inscrite auprès du ServiceScope racine.

createAndProvide(serviceKey, simpleServiceClass)

Il s’agit d’une fonction abrégée qui équivaut à construire une nouvelle instance du simpleServiceClass, puis à l’inscrire en appelant ServiceScope.provide().

createAndProvide<T>(serviceKey: ServiceKey<T>, simpleServiceClass: {
        new (serviceScope: ServiceScope): T;
    }): T;

Paramètres

serviceKey

ServiceKey<T>

clé pouvant servir ultérieurement pour utiliser le service

simpleServiceClass

{ new (serviceScope: ServiceScope): T; }

classe TypeScript à créer

Retours

T

une instance de simpleServiceClass qui vient d’être créée

createDefaultAndProvide(serviceKey)

Il s’agit d’une fonction de raccourci qui construit l’implémentation par défaut du serviceKey spécifié, puis l’enregistre en appelant ServiceScope.provide().

createDefaultAndProvide<T>(serviceKey: ServiceKey<T>): T;

Paramètres

serviceKey

ServiceKey<T>

clé pouvant servir ultérieurement pour utiliser le service

Retours

T

une instance de service qui a été construite à l’aide de ServiceKey.defaultCreator

finish()

Termine la séquence d’initialisation pour une étendue de service.

finish(): void;

Retours

void

Remarques

Lorsqu’un ServiceScope est démarré pour la première fois, il est dans un état « inachevé » où provide() est autorisé, mais consume() est interdit. Après avoir appelé finish(), consume() est autorisé, mais provide() n’est pas autorisé.

Ce formalisme empêche un certain nombre de situations complexes qui pourraient entraîner des bogues. Par exemple, supposé que Scope2 est un enfant de Scope1, et Scope1 fournit instance A1 de l’interface A. Si quelqu’un consomme A1 à partir d’Scope2 (via l’héritage) avant l’appel de Scope2.provide() avec A2, un appel ultérieur à Scope2.consume() peut retourner un résultat différent de l’appel précédent. Ce non-déterminisme peut entraîner des résultats imprévisibles qui sont difficiles à diagnostiquer.

getParent()

Renvoie le parent du ServiceScope actuel ou « Undefined » s’il s’agit d’une étendue racine.

getParent(): ServiceScope | undefined;

Retours

ServiceScope | undefined

l’étendue du service parent

provide(serviceKey, service)

Ajouter un nouveau service à une étendue de service.

provide<T>(serviceKey: ServiceKey<T>, service: T): T;

Paramètres

serviceKey

ServiceKey<T>

clé qui servira ultérieurement pour utiliser le service

service

T

instance du service en cours d’enregistrement

Retours

T

le même objet qui a été transféré comme paramètre « service »

Remarques

ServiceScope.provide() est utilisé pour inscrire une implémentation de serviceKey donnée pour l’étendue actuelle et une implémentation d’une rootServiceKey donnée pour l’étendue racine. Il peut être utilisé uniquement lorsque le ServiceScope est défini sur l’état « Undefined », c'est-à-dire avant que finish() ait été appelé.

startNewChild()

Construit un nouveau ServiceScope qui est un enfant de l’étendue actuelle.

startNewChild(): ServiceScope;

Retours

le nouveau ServiceScope racine créé

Remarques

Les étendues de service forment une arborescence, de sorte que lors de l’utilisation d’un service, si la clé n’est pas fournie explicitement par une étendue enfant, la hiérarchie parente est consultée.

startNewRoot()

Créez un nouveau ServiceScope de niveau racine. Seules les étendues de niveau racine peuvent créer automatiquement des implémentations par défaut de ServiceKeys.

static startNewRoot(): ServiceScope;

Retours

le nouveau ServiceScope racine créé

whenFinished(callback)

Différer une opération jusqu’à ce que ServiceScope.finish() soit terminé.

whenFinished(callback: () => void): void;

Paramètres

callback

() => void

Bloc de code qui doit appeler ServiceScope.consume()

Retours

void

Remarques

L’appel de ServiceScope.consume() avant l’appel de finish() est une erreur. La façon la plus fiable de protéger votre composant contre cette erreur consiste à effectuer les appels consume() à l’intérieur d’un rappel whenFinished(). Si l’étendue du service est déjà terminée, le rappel est exécuté immédiatement ; sinon, elle sera exécutée ultérieurement une fois l’étendue terminée.

REMARQUE : Il ne s’agit pas d’un rappel asynchrone. L’initialisation de ServiceScope est généralement peu coûteuse et de courte durée. Toutefois, le flux de contrôle passe souvent par de nombreux constructeurs et classes de base, ce qui peut être simplifié à l’aide de whenFinished().