Compartilhar via


Estendendo a hospedagem com ServiceHostFactory

A API ServiceHost padrão para serviços de hospedagem no Windows Communication Foundation (WCF) é um ponto de extensibilidade na arquitetura WCF. Os usuários podem derivar suas próprias classes de host de ServiceHost, geralmente para substituir OnOpening() para usar ServiceDescription para adicionar pontos de extremidade padrão de forma imperativa ou modificar comportamentos, antes de abrir o serviço.

No ambiente self-host, você não precisa criar um ServiceHost personalizado porque escreve o código que instancia o host e então chama Open() nele depois de instanciar. Entre essas duas etapas você pode fazer o que quiser. Você pode, por exemplo, adicionar um novo IServiceBehavior:

public static void Main()  
{  
   ServiceHost host = new ServiceHost( typeof( MyService ) );  
   host.Description.Add( new MyServiceBehavior() );  
   host.Open();  
  
   ...  
}  

Esta abordagem não é reutilizável. O código que manipula a descrição é codificado no programa host (neste caso, a função Main()), portanto, é difícil reutilizar essa lógica em outros contextos. Há também outras maneiras de adicionar um IServiceBehavior que não exigem código imperativo. Você pode derivar um atributo de ServiceBehaviorAttribute e colocá-lo em seu tipo de implementação de serviço ou pode tornar um comportamento personalizado configurável e compô-lo dinamicamente usando a configuração.

No entanto, uma pequena variação do exemplo também pode ser usada para resolver esse problema. Uma abordagem é mover o código que adiciona o ServiceBehavior de Main() para o método OnOpening de um derivado personalizado de ServiceHost:

public class DerivedHost : ServiceHost  
{  
   public DerivedHost( Type t, params Uri baseAddresses ) :  
      base( t, baseAddresses ) {}  
  
   public override void OnOpening()  
   {  
  this.Description.Add( new MyServiceBehavior() );  
   }  
}  

Então, dentro de Main() você pode usar:

public static void Main()  
{  
   ServiceHost host = new DerivedHost( typeof( MyService ) );  
   host.Open();  
  
   ...  
}  

Agora você encapsulou a lógica personalizada em uma abstração limpa que pode ser facilmente reutilizada em muitos executáveis de host diferentes.

Não é imediatamente óbvio como usar este ServiceHost personalizado de dentro dos Serviços de Informações da Internet (IIS) ou do Serviço de Ativação de Processos do Windows (WAS). Esses ambientes são diferentes do ambiente de auto-hospedagem, porque o ambiente de hospedagem é aquele que instancia o ServiceHost em nome do aplicativo. A infraestrutura de hospedagem IIS e WAS não sabe nada sobre seu derivado ServiceHost personalizado.

O ServiceHostFactory foi projetado para resolver esse problema de acessar seu ServiceHost personalizado de dentro do IIS ou WAS. Como um host personalizado derivado de ServiceHost é configurado dinamicamente e potencialmente de vários tipos, o ambiente de hospedagem nunca o instancia diretamente. Em vez disso, o WCF usa um padrão de fábrica para fornecer uma camada de indireção entre o ambiente de hospedagem e o tipo concreto do serviço. A menos que você diga o contrário, ele usa uma implementação padrão de ServiceHostFactory que retorna uma instância de ServiceHost. Mas você também pode fornecer sua própria fábrica que retorna seu host derivado especificando o nome do tipo CLR de sua implementação de fábrica na diretiva @ServiceHost.

A intenção é que, para casos básicos, implementar sua própria fábrica seja um exercício simples. Por exemplo, aqui está um ServiceHostFactory personalizado que retorna um ServiceHost derivado:

public class DerivedFactory : ServiceHostFactory  
{  
   public override ServiceHost CreateServiceHost( Type t, Uri[] baseAddresses )  
   {  
      return new DerivedHost( t, baseAddresses )  
   }  
}  

Para usar esta fábrica em vez da fábrica padrão, forneça o nome do tipo na diretiva @ServiceHost da seguinte maneira:

<% @ServiceHost Factory="DerivedFactory" Service="MyService" %>

Embora não haja limite técnico para fazer o que você deseja no ServiceHost retornado de CreateServiceHost, sugerimos que você mantenha suas implementações de fábrica o mais simples possível. Se você tiver muita lógica personalizada, é melhor colocar essa lógica dentro do seu host em vez de dentro da fábrica para que possa ser reutilizável.

Há mais uma camada para a API de hospedagem que deve ser mencionada aqui. O WCF também tem ServiceHostBase e ServiceHostFactoryBase, dos quais derivam ServiceHost e ServiceHostFactory respectivamente. Eles existem para cenários mais avançados em que você deve trocar grandes partes do sistema de metadados por suas próprias criações personalizadas.