Condividi tramite


Estensione dell'hosting tramite ServiceHostFactory

L'API standard ServiceHost per l'hosting di servizi in Windows Communication Foundation (WCF) è un punto di estendibilità nell'architettura WCF. Gli utenti possono derivare le proprie classi host da ServiceHost, in genere per eseguire l'override di OnOpening() e utilizzare ServiceDescription per aggiungere endpoint predefiniti in modo imperativo o modificare i comportamenti, prima di aprire il servizio.

Nell'ambiente self-host non è necessario creare un ServiceHost personalizzato perché si scrive il codice che istanzia l'host e quindi si chiama Open() su di esso dopo averlo istanziato. Tra questi due passaggi è possibile eseguire qualsiasi operazione desiderata. È possibile, ad esempio, aggiungere un nuovo IServiceBehavior:

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

Questo approccio non è riutilizzabile. Il codice che modifica la descrizione viene codificato nel programma host (in questo caso, la funzione Main(), quindi è difficile riutilizzare tale logica in altri contesti. Esistono anche altri modi per aggiungere un oggetto IServiceBehavior che non richiede codice imperativo. È possibile derivare un attributo da ServiceBehaviorAttribute e inserirlo nel tipo di implementazione del servizio oppure è possibile rendere configurabile un comportamento personalizzato e componerlo in modo dinamico usando la configurazione.

Tuttavia, è anche possibile usare una leggera variazione dell'esempio per risolvere questo problema. Un approccio consiste nello spostare il codice che aggiunge ServiceBehavior all'esterno di Main() e all'interno del metodo OnOpening di un derivato personalizzato di ServiceHost.

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

Quindi, all'interno di Main() è possibile usare:

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

Hai ora incapsulato la logica personalizzata in un'astrazione pulita che può essere facilmente riutilizzata in molti diversi eseguibili host.

Non è immediatamente chiaro come usare questo componente personalizzato ServiceHost all'interno di Internet Information Services (IIS) o del Servizio di Attivazione dei Processi Windows (WAS). Questi ambienti sono diversi dall'ambiente self-host, perché l'ambiente di hosting è quello che crea un'istanza ServiceHost di per conto dell'applicazione. L'infrastruttura di hosting IIS e WAS non conosce nulla sulla derivata personalizzata ServiceHost .

ServiceHostFactory è stato progettato per risolvere il problema dell'accesso al tuo ServiceHost personalizzato all'interno di IIS o WAS. Poiché un host personalizzato derivato da ServiceHost viene configurato dinamicamente e potenzialmente di vari tipi, l'ambiente di hosting non lo instanzia mai direttamente. WCF usa invece un modello factory per fornire un livello di riferimento indiretto tra l'ambiente di hosting e il tipo concreto del servizio. Se non diversamente specificato, usa un'implementazione predefinita di ServiceHostFactory che restituisce un'istanza di ServiceHost. È possibile fornire anche una factory personalizzata che restituisca l'host derivato, specificando nella direttiva @ServiceHost il nome del tipo CLR dell'implementazione della factory.

Lo scopo è che per i casi di base, l'implementazione della propria factory deve essere un esercizio semplice. Ecco, ad esempio, un oggetto personalizzato ServiceHostFactory che restituisce un derivato ServiceHost:

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

Per usare questa factory anziché la factory predefinita, specificare il nome del tipo nella @ServiceHost direttiva come indicato di seguito:

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

Anche se non esiste alcun limite tecnico per eseguire ciò che si vuole restituire ServiceHost da CreateServiceHost, è consigliabile mantenere le implementazioni di factory il più semplice possibile. Se si dispone di una grande logica personalizzata, è preferibile inserire tale logica all'interno dell'host anziché all'interno della factory in modo che possa essere riutilizzabile.

C'è un altro livello per l'API di hosting che deve essere menzionato qui. WCF ha anche ServiceHostBase e ServiceHostFactoryBase, da cui derivano rispettivamente ServiceHost e ServiceHostFactory. Esistono per scenari più avanzati in cui è necessario scambiare parti di grandi dimensioni del sistema di metadati con le proprie creazioni personalizzate.