Estendendo a hospedagem usando ServiceHostFactory

A API padrão ServiceHost 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 , geralmente para substituir OnOpening() para usar ServiceDescription para adicionar pontos de extremidade padrão imperativamente ou modificar comportamentos, antes de ServiceHostabrir o serviço.

No ambiente de auto-host, você não precisa criar um personalizado ServiceHost porque você escreve o código que instancia o host e, em seguida, chamá-lo Open() depois de instanciá-lo. Entre esses dois passos você pode fazer o que quiser. 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(), por isso é 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 e colocá-lo em seu tipo de implementação de ServiceBehaviorAttribute 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 este problema. Uma abordagem é mover o código que adiciona o ServiceBehavior de Main() e para o OnOpening método de uma derivada personalizada 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ê encapsula 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 esse costume ServiceHost 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-host, porque o ambiente de hospedagem é aquele que instancia o ServiceHost em nome do aplicativo. A infraestrutura de hospedagem do IIS e do WAS não sabe nada sobre seu derivado personalizado ServiceHost .

O ServiceHostFactory foi projetado para resolver esse problema de acessar seu personalizado ServiceHost de dentro do IIS ou WAS. Como um host personalizado derivado é configurado dinamicamente e potencialmente de vários tipos, o ambiente de ServiceHost 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 que ServiceHostFactory 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 @ServiceHost diretiva.

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

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 da @ServiceHost seguinte maneira:

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

Embora não haja limite técnico para fazer o que você quer para o ServiceHost retorno de CreateServiceHostvocê, 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 ela possa ser reutilizável.

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