Compartilhar via


Itens essenciais do serviço agenciado

Um serviço agenciado é um serviço adquirido por meio de um IServiceBroker e é exposto como uma interface compatível com RPC para permitir que o serviço e seu cliente existam em AppDomains distintos, processos ou até mesmo em máquinas (no caso do Live Share). O serviço agenciado pode ser oferecido a partir do processo principal do Visual Studio ou de processos auxiliares, e pode ser consumido por uma extensão do Visual Studio em qualquer um desses processos.

Mais serviços do Visual Studio (não intermediados) estão disponíveis por meio da IServiceProvider interface, conforme descrito em Usando e Fornecendo Serviços. Normalmente, esses serviços só estão disponíveis no processo principal do Visual Studio, mas expõem um conjunto maior de funcionalidades do que os serviços agenciados.

Uma extensão do Visual Studio em execução em um convidado do Live Share pode fornecer funcionalidade adicional acessando um subconjunto desses serviços, conforme oferecido pelo host do Live Share. As verificações de autorização se aplicam em conexões do Live Share para atenuar o risco de um convidado do Live Share mal comportado comprometer a segurança do host do Live Share. Os autores de serviços agenciados que optam por expor seus serviços pelo Live Share devem ter cuidado para implementar verificações de autorização, conforme descrito em Como fornecer um serviço agenciado.

Corretor de serviços

O Visual Studio possui uma instância global IServiceBroker, semelhante a (e recuperável do) GlobalProvider do qual expõe outro serviço. O MEF também pode ser utilizado para recuperá-lo.

Pode haver outros agentes de serviço específicos para determinado contexto disponibilizados por recursos específicos do Visual Studio, que desejam combinar o agente global com um deles, fornecendo serviços adicionais (ou talvez suprimindo alguns).

Um IServiceBroker é, intencionalmente, uma caixa preta que permite ao cliente obter serviços que podem ser locais, em outro processo, ou em outra máquina. Os agentes de serviço podem ser agregações de um ou muitos outros, com políticas aplicadas.

Com base no contexto em que o processo do Visual Studio está, esse corretor de serviço global é uma agregação de um conjunto variável de outros corretores de serviço. As alterações de contexto no processo podem alterar o conjunto de serviços agenciados que podem ser ativados. Por exemplo, quando uma solução é carregada, um serviço especificamente relacionado à solução ativa pode ficar disponível. Esse mesmo serviço também pode estar disponível em um modo de exibição Abrir Pasta, embora com uma implementação de suporte diferente. A alteração na implementação do serviço seria transparente para um cliente desse serviço, uma vez que ambas as implementações devem cumprir o mesmo contrato, mas o cliente é obrigado a consultar novamente o serviço nessa alteração de contexto (da qual eles seriam notificados por AvailabilityChanged) para obter a nova instância.

O agente de serviço normalmente é usado para obter um proxy para o serviço. Ou seja, em vez de receber uma referência diretamente ao objeto de serviço, o cliente recebe um stub que encaminha todas as chamadas de método para o serviço e resultados ou exceções de volta para o cliente. Ele também pode encaminhar eventos gerados pelo serviço para o cliente. Em alguns casos, um serviço pode dar suporte ou exigir que o cliente ofereça um "objeto de destino" no qual o serviço pode invocar métodos para chamar de volta ao cliente.

Contêiner de serviço agenciado

Os serviços devem ser propostos no IBrokeredServiceContainer para que estejam disponíveis no IServiceBroker global. Esse contêiner de serviço é responsável não apenas por expor a fábrica de serviço ao corretor de serviço, mas também por controlar quais clientes têm acesso ao serviço e por notificar esses clientes quando o acesso a esse serviço for alterado.

Composição de um serviço intermediado

Um serviço agenciado consiste nos seguintes elementos:

  • Uma interface que declara a funcionalidade do serviço e serve como um contrato entre o serviço e seus clientes.
  • Uma implementação dessa interface.
  • Um ServiceMoniker para atribuir um nome e uma versão ao serviço.
  • Um ServiceRpcDescriptor que combina ServiceMoniker com comportamento para lidar com RPC, quando necessário.
  • Código para oferecer a fábrica de serviços
  • Registro do serviço

Interface de serviço

Pode ser uma interface .NET padrão (geralmente escrita em C#). Para permitir que os clientes e serviços agenciados existam em processos distintos e se comuniquem por RPC, essa interface deve cumprir as restrições especificadas pelo ServiceRpcDescriptor que seu serviço usará. Essas restrições normalmente incluem que propriedades e indexadores não são permitidos e a maioria ou todos os métodos retornam Task ou outro tipo de retorno compatível com assíncrono.

Nomes e descritores de serviços intermediados

Ativar um serviço requer saber seu moniker. Como o moniker está incluído no descritor do serviço, um cliente normalmente pode lidar apenas com o ServiceRpcDescriptor. Um descritor adiciona o comportamento necessário para configurar uma conexão RPC entre o serviço agenciado e seu cliente ou quando necessário para serializar chamadas RPC de/para um Stream.

O Visual Studio recomenda o uso do tipo derivado ServiceJsonRpcDescriptor para serviços agenciados que utilizam a biblioteca StreamJsonRpc quando o cliente e o serviço precisam de RPC para se comunicar. O StreamJsonRpc aplica determinadas restrições na interface de serviço conforme descrito aqui .

Um descritor raramente precisa ser usado diretamente. Em vez disso, normalmente é adquirido de VisualStudioServices ou de uma biblioteca que oferece o serviço e, em seguida, usado como um argumento para GetProxyAsync.

As classes ServiceMoniker e ServiceJsonRpcDescriptor são imutáveis e, portanto, seguras para compartilhar como campos ou propriedades static readonly. Qualquer outro ServiceRpcDescriptortipo derivado deve ser imutável.

A ServiceMoniker é serializável. A ServiceJsonRpcDescriptor não é serializável.

Público-alvo do serviço

Cada serviço agenciado é registrado com um conjunto de flags de ServiceAudience. Esses sinalizadores controlam a quais clientes e sobre quais conexões o serviço agenciado será exposto.

Uma seleção típica é ServiceAudience.Local, que expõe o serviço a qualquer processo local em uma sessão do Visual Studio. Com essa configuração, o serviço é sempre ativado localmente, mesmo que uma sessão Live Shared esteja ativa.

Quando o ServiceAudience.LiveShareGuest sinalizador é adicionado, um convidado do Live Share que solicita esse serviço agenciado obterá um proxy para esse serviço agenciado pela conexão remota com o host do Live Share.

Qualquer combinação de flags definidos em ServiceAudience é legal. O LiveShareGuest sinalizador pode ser definido sem também definir o Local sinalizador, por exemplo, para expor um serviço agenciado somente aos convidados do Live Share (de um host do Live Share) e nunca estar disponível localmente (onde o cliente e o serviço estão no mesmo processo).

Os flags RemoteExclusiveClient e RemoteExclusiveServer são preteridos.

Quando um cliente solicita um serviço intermediado, ele não precisa saber o ServiceAudience para esse serviço ou onde o serviço será ativado. No entanto, pode ser útil para um serviço documentar esse valor e para um desenvolvedor que está consumindo o serviço estar ciente de onde um serviço pode ser ativado para que ele possa prever o tipo de dados que podem estar provenientes desse serviço em vários contextos e quando um serviço pode estar disponível.

Composição de um cliente agenciado

Quando um cliente solicita um serviço agenciado, o cliente recebe null de volta quando o serviço não está disponível, uma ServiceActivationFailedException é lançada se o serviço falha na ativação, ou obtém um proxy para o serviço. Um proxy é utilizado independentemente de o serviço intermediado ser ativado no mesmo processo que o cliente ou em um diferente. Esse proxy ajuda a harmonizar padrões de uso entre os casos de serviço local e remoto para que o cliente não precise estar ciente de onde o serviço está localizado.