Serviços essenciais intermediados

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, processos ou até mesmo entre máquinas distintas (no caso do Live Share). O serviço agenciado pode ser oferecido a partir do processo principal do Visual Studio ou alguns de seus processos auxiliares e pode ser consumido por qualquer um desses processos por uma extensão do Visual Studio.

Mais serviços (não intermediados) do Visual Studio estão disponíveis por meio da interface, IServiceProvider conforme descrito em Usando e fornecendo serviços. Esses serviços normalmente 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 a conexões do Live Share para reduzir o risco de um convidado do Live Share com comportamento inadequado comprometer a segurança do host do Live Share. Os autores de serviços intermediados que optarem por expor seus serviços no Live Share devem ter o cuidado de implementar verificações de autorização, conforme descrito em Como fornecer um serviço intermediado.

Service Broker

O Visual Studio tem um global IServiceBroker, análogo (e recuperável de) o GlobalProvider que expõe outro serviço. Ele também pode ser recuperado via MEF.

Pode haver outros agentes de serviço específicos de contexto oferecidos por recursos específicos do Visual Studio que desejam agregar o global com um de seus próprios que oferece serviços adicionais (ou talvez suprima alguns).

Um IServiceBroker é (intencionalmente) uma caixa preta que permite que um cliente obtenha serviços que podem ser locais, em outro processo ou em outra máquina. Os service brokers podem ser agregados de um ou muitos outros, com políticas aplicadas.

Com base no contexto em que o processo do Visual Studio está, esse agente de serviço global é uma agregação de um conjunto variável de outros agentes de serviço. Alterações de contexto dentro do processo podem alterar o conjunto de serviços intermediados 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 Pasta Aberta, 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 através dessa alteração de contexto (da qual seria notificado via AvailabilityChanged) para obter a nova instância.

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

Contêiner de serviço agenciado

Os serviços devem ser oferecidos no IBrokeredServiceContainer para estarem disponíveis no global IServiceBroker. Esse contêiner de serviço é responsável não apenas por expor a fábrica de serviços ao agente de serviços, mas também por controlar quais clientes têm acesso ao serviço e 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.
  • A ServiceMoniker para atribuir um nome e uma versão ao serviço.
  • A ServiceRpcDescriptor que combina o com comportamento ServiceMoniker 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

Isso pode ser uma interface .NET padrão (geralmente escrita em C#). Para permitir que clientes e serviços de serviços intermediados existam em processos distintos e se comuniquem por RPC, essa interface deve obedecer às restrições especificadas pelo ServiceRpcDescriptor que seu serviço usará. Essas restrições geralmente 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íncronos.

Apelidos e descritores de serviço intermediados

Ativar um serviço requer conhecer seu apelido. Como o apelido está incluído no descritor do serviço, um cliente normalmente pode apenas lidar 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 Streamarquivo .

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

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

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

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

Público de atendimento

Cada serviço intermediado é registrado com uma seleção de bandeiras da ServiceAudience. Esses sinalizadores controlam 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 dentro de uma sessão do Visual Studio. Com essa configuração, o serviço é sempre ativado localmente, mesmo se uma sessão Live Shared estiver ativa.

Quando o 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 ServiceAudience.LiveShareGuest host do Live Share.

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

Os RemoteExclusiveClient e RemoteExclusiveServer sinalizadores foram preteridos.

Quando um cliente solicita um serviço intermediado, ele não precisa saber qual é o ServiceAudience 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 eles possam antecipar o tipo de dados que podem estar vindo desse serviço em vários contextos e quando um serviço pode estar disponível.

Composição de um cliente intermediado

Quando um cliente solicita um serviço agenciado, ele retorna null quando o serviço não está disponível, um lançamento se o serviço falhar na ativação ou obtém um ServiceActivationFailedExceptionproxy para o serviço. Um proxy é usado se o serviço agenciado estiver ativado no mesmo processo que o cliente ou em um processo diferente. Esse proxy ajuda a harmonizar os padrões de uso entre os casos de serviço local e remoto para que o cliente não precise saber onde o serviço está localizado.