Partager via


Éléments essentiels du service intermédiaire

Un service intermédiaire est un service acquis via un IServiceBroker, et est exposé en tant qu’interface compatible RPC pour permettre au service et à son client d’exister dans des AppDomains distincts, des processus ou même sur des machines différentes (dans le cas de Live Share). Le service réparti peut être profferé à partir du processus Visual Studio principal ou de certains de ses processus auxiliaires, et peut être consommé par l’un de ces processus par une extension Visual Studio.

D'autres services Visual Studio (non courtagés) sont disponibles via l’interface IServiceProvider comme décrit dans Utilisation et fourniture de services. Ces services sont généralement disponibles uniquement dans le processus principal de Visual Studio, mais exposent un plus grand ensemble de fonctionnalités que les services réparti.

Une extension de Visual Studio s'exécutant sur un invité Live Share peut fournir des fonctionnalités supplémentaires en accédant à un sous-ensemble de ces services comme offert par l'hôte Live Share. Les vérifications d’autorisation s’appliquent sur les connexions Live Share pour atténuer le risque d’un invité Live Share mal comportementant qui compromet la sécurité de l’hôte Live Share. Les auteurs de services réparti qui choisissent d’exposer leurs services sur Live Share doivent prendre soin d’implémenter des vérifications d’autorisation, comme décrit dans Comment fournir un service réparti.

Courtier de services

Visual Studio a un élément global IServiceBroker, analogue à GlobalProvider (et récupérable à partir de celui-ci), qui expose d'autres services. Il peut également être récupéré via MEF.

Il peut y avoir d’autres répartiteurs de services spécifiques au contexte proposés par des fonctionnalités Visual Studio spécifiques qui souhaitent agréger l’ensemble avec l’un de leurs propres services qui propose des services supplémentaires (ou peut-être supprimer certains).

Un IServiceBroker est intentionnellement une boîte noire qui permet à un client d'obtenir des services qui peuvent être locaux, dans un autre processus ou sur un autre ordinateur. Les répartiteurs de services peuvent être des agrégats d’un ou de plusieurs autres, avec des stratégies appliquées.

En fonction du contexte dans lequel se trouve le processus Visual Studio, ce service broker global est un agrégat d’un ensemble changeant d’autres répartiteurs de services. Les modifications de contexte au sein du processus peuvent modifier l’ensemble des services intermédiaires qui peuvent être activés. Par exemple, lorsqu’une solution est chargée, un service spécifiquement lié à la solution active peut devenir disponible. Ce même service peut également être disponible dans une vue Dossier ouvert, bien qu'avec une implémentation sous-jacente différente. La modification de l’implémentation du service serait transparente pour un client de ce service, car les deux implémentations doivent remplir le même contrat, mais le client doit interroger à nouveau le service dans ce changement de contexte (dont ils seraient avertis via AvailabilityChanged) pour obtenir la nouvelle instance.

Le service Broker est généralement utilisé pour obtenir un proxy vers le service. Autrement dit, au lieu de recevoir directement une référence à l’objet de service, le client reçoit un stub qui transfère tous les appels de méthode au service et les résultats ou exceptions au client. Il peut également transférer des événements déclenchés par le service au client. Dans certains cas, un service peut prendre en charge ou exiger que le client fournisse un « objet cible » sur lequel le service peut invoquer des méthodes pour retourner l'appel au client.

Conteneur de service intermédiaire

Les services doivent être offerts dans le IBrokeredServiceContainer pour être disponibles depuis le IServiceBroker global. Ce conteneur de service est responsable non seulement de l'exposition de la fabrique de services au Service Broker, mais également de contrôler quels clients ont accès au service et de les notifier lorsque l'accès à ce service change.

Composition d’un service intermédiaire

Un service intermédiaire se compose des éléments suivants :

  • Interface qui déclare la fonctionnalité du service et sert de contrat entre le service et ses clients.
  • Implémentation de cette interface.
  • A ServiceMoniker pour attribuer un nom et une version au service.
  • Un ServiceRpcDescriptor qui combine le ServiceMoniker avec le comportement pour gérer le RPC si nécessaire.
  • Code pour proposer l'usine de services
  • Inscription du service

Interface de service

Il peut s’agir d’une interface .NET standard (souvent écrite en C#). Pour permettre aux clients et services de service réparti d’exister dans des processus distincts et de communiquer via RPC, cette interface doit respecter les restrictions spécifiées par le ServiceRpcDescriptor service que votre service utilisera. Ces restrictions incluent généralement que les propriétés et les indexeurs ne sont pas autorisés, et la plupart ou toutes les méthodes retournent Task ou un autre type de retour compatible asynchrone.

Identificateurs et descripteurs de service intermédié

L’activation d’un service nécessite de connaître son moniker. Étant donné que le moniker est inclus dans le descripteur du service, un client peut généralement simplement traiter le ServiceRpcDescriptor. Un descripteur ajoute le comportement nécessaire pour configurer une connexion RPC entre le service réparti et son client ou lorsque nécessaire pour sérialiser les appels RPC vers/à partir d’un Stream.

Visual Studio recommande d’utiliser le ServiceJsonRpcDescriptor type dérivé pour les services répartits qui utilisent la bibliothèque StreamJsonRpc lorsque le client et le service nécessitent une communication RPC. StreamJsonRpc applique certaines restrictions à l’interface de service comme décrit ici.

Un descripteur doit rarement être utilisé directement. Au lieu de cela, il est généralement obtenu à partir de VisualStudioServices ou d'une bibliothèque qui offre le service, et ensuite utilisé comme argument à GetProxyAsync.

Les classes ServiceMoniker et ServiceJsonRpcDescriptor sont immuables et donc sécurisées à partager en tant que champs ou propriétés static readonly. Tout autre ServiceRpcDescriptortype dérivé doit être immuable.

A ServiceMoniker est sérialisable. Un ServiceJsonRpcDescriptor n’est pas sérialisable.

Audience du service

Chaque service intermédiaire est inscrit avec une sélection de drapeaux de ServiceAudience. Ces drapeaux contrôlent quels clients et sur quelles connexions le service intermédiaire sera exposé.

Une sélection classique est ServiceAudience.Local, qui expose le service à n’importe quel processus local au sein d’une session Visual Studio. Avec ce paramètre, le service est toujours activé localement, même si une session Live Shared est active.

Lorsque l’indicateur ServiceAudience.LiveShareGuest est ajouté, un invité Live Share qui demande un service intermédiaire obtiendra un proxy vers ce service intermédiaire via la connexion à distance avec l’hôte Live Share.

Toute combinaison d'indicateurs définis sur ServiceAudience est légale. L’indicateur LiveShareGuest peut être défini sans également définir l’indicateur Local , par exemple pour exposer un service réparti uniquement aux invités Live Share (à partir d’un hôte Live Share) et ne jamais être disponible localement (où le client et le service se trouvent dans le même processus).

Les drapeaux RemoteExclusiveClient et RemoteExclusiveServer sont déconseillés.

Lorsqu’un client demande un service intermédiaire, il n’a pas besoin de savoir ce qu'il en est pour ce service ni l'endroit où le service sera activé. Toutefois, il peut être utile pour un service de documenter cette valeur et pour un développeur qui consomme le service pour savoir où un service peut être activé afin qu’il puisse anticiper le type de données provenant de ce service dans différents contextes et lorsqu’un service peut être disponible.

Composition d’un client réparti

Lorsqu’un client demande un service assuré par un intermédiaire, il reçoit null lorsque le service n’est pas disponible, une exception ServiceActivationFailedException est levée si l’activation du service échoue, ou il obtient un proxy pour accéder au service. Un proxy est utilisé si le service réparti est activé dans le même processus que le client ou un autre. Ce proxy permet d’harmoniser les modèles d’utilisation dans les cas de service local et distant afin que le client ne sache pas où se trouve le service.