Compartilhar via


Estendendo a hospedagem usando ServiceHostFactory

A API padrão ServiceHost para serviços de hospedagem no WCF (Windows Communication Foundation) é um ponto de extensibilidade na arquitetura WCF. Os usuários podem derivar suas próprias classes de host de ServiceHost, geralmente para sobrescrever OnOpening() ou para usar ServiceDescription a fim de 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();  
  
   ...  
}  

Essa abordagem não é reutilizável. O código que manipula a descrição é codificado no programa host (nesse 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() );  
   }  
}  

Em seguida, 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 reutilizada facilmente em vários executáveis hospedeiros.

Não é imediatamente óbvio como usar essa personalização ServiceHost a partir 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, pois o ambiente de hospedagem é aquele que instancia ServiceHost em nome do aplicativo. A infraestrutura de hospedagem IIS e WAS não sabe nada sobre sua derivada personalizada ServiceHost .

O ServiceHostFactory foi projetado para resolver o problema de acessar seu ServiceHost customizado a partir do IIS ou WAS. Como um host personalizado que é derivado de ServiceHost é configurado dinamicamente, com potencial para ser 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 da ServiceHostFactory qual 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, nos casos básicos, implementar a sua própria fábrica deve ser 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 essa 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 host em vez de dentro da fábrica para que ela 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, do qual ServiceHost e ServiceHostFactory , respectivamente, derivam. Elas 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.