Extensión del hospedaje mediante ServiceHostFactory

La API ServiceHost estándar para hospedar servicios en Windows Communication Foundation (WCF) es un punto de extensibilidad en la arquitectura de WCF. Los usuarios pueden derivar sus propias clases de host a partir de ServiceHost, normalmente para invalidar OnOpening para utilizar ServiceDescription para agregar extremos predeterminados de manera imperativa o modificar comportamientos, antes de abrir el servicio.

En el entorno de autohospedaje, no tiene que crear un ServiceHost personalizado, puesto que escribe el código que crea instancias del host y, a continuación, llama al método Open en él después de haber creado instancias de él. Entre esos dos pasos puede hacer lo que quiera. Podría, por ejemplo, agregar un nuevo IServiceBehavior:

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

Este enfoque no es reutilizable. El código que manipula la descripción está codificado en el programa host (en este caso, la función Main()), por lo que es difícil reutilizar esa lógica en otros contextos. Hay también otras maneras de agregar un IServiceBehavior que no requieren código imperativo. Puede derivar un atributo a partir de ServiceBehaviorAttribute y colocarlo en su tipo de implementación de servicio o puede crear un comportamiento personalizado configurable y componerlo dinámicamente mediante configuración.

Sin embargo, también se puede utilizar una pequeña variación del ejemplo para resolver este problema. Un enfoque es sacar el código que agrega el ServiceBehavior fuera de Main() y meterlo en el método OnOpening de una 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() );
   }
}

A continuación, dentro de Main() puede utilizar:

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

Ahora ha encapsulado la lógica personalizada en una abstracción limpia que se puede reutilizar con facilidad en muchas aplicaciones ejecutables diferentes de host.

El uso de este ServiceHost personalizado desde dentro de Internet Information Services (IIS) o Windows Process Activation Service (WAS) no es totalmente obvio. Esos entornos son diferentes del entorno de autohospedaje, porque el entorno de hospedaje es el que está creando instancias del ServiceHost en nombre de la aplicación. La infraestructura de hospedaje de IIS y WAS no sabe nada sobre su derivado de ServiceHost personalizado.

ServiceHostFactory se diseñó para resolver este problema de tener acceso a su ServiceHost personalizado desde dentro de IIS o WAS. Dado que un host personalizado que se deriva a partir de ServiceHost se configura dinámicamente y es probablemente de varios tipos, el entorno de hospedaje nunca crea instancias de él directamente. En su lugar, WCF utiliza un modelo de generador para proporcionar una capa de direccionamiento indirecto entre el entorno de hospedaje y el tipo concreto del servicio. A menos que indique lo contrario, utiliza una implementación predeterminada de ServiceHostFactory que devuelve una instancia de ServiceHost. Pero también puede proporcionar su propio generador que devuelva su host derivado especificando el nombre de tipo de CLR de su implementación del generador en la directiva @ServiceHost .

El propósito es que para los casos básicos, la implementación de su propio generador debería ser un ejercicio sencillo. Por ejemplo, aquí hay un ServiceHostFactory personalizado que devuelve un ServiceHostderivado:

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

Para utilizar este generador en lugar del generador predeterminado, proporcione el nombre de tipo en la directiva @ServiceHost de la siguiente manera:

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

Mientras no haya ningún límite técnico para hacer lo que desea al ServiceHost que devuelve desde CreateServiceHost, sugerimos que mantenga sus implementaciones de generador lo más simple posible. Si tiene mucha lógica personalizada, es mejor colocar esa lógica dentro de su host en lugar de dentro del generador, para que pueda reutilizarse.

Hay una capa más sobre la API de hospedaje que se debería mencionar aquí. WCF también tiene ServiceHostBase y ServiceHostFactoryBase, desde los que ServiceHost y ServiceHostFactory se derivan respectivamente. Existen para escenarios más avanzados donde debe reemplazar grandes partes del sistema de metadatos con sus propias creaciones personalizadas.