Teilen über


Erweitern des Hostings mithilfe von ServiceHostFactory

Die Standard-API ServiceHost für Hostingdienste in Windows Communication Foundation (WCF) ist ein Erweiterbarkeitspunkt in der WCF-Architektur. Benutzer können ihre eigenen Hostklassen von ServiceHost ableiten, in der Regel überschreiben sie OnOpening(), verwenden ServiceDescription um Standardendpunkte imperativ hinzuzufügen oder Verhaltensweisen zu ändern, bevor sie den Dienst öffnen.

In der selbst gehosteten Umgebung müssen Sie keine benutzerdefinierte ServiceHost-Klasse erstellen, weil Sie den Code schreiben, der den Host instantiiert, und rufen anschließend Open() für den Host auf. Zwischen diesen beiden Schritten können Sie alles tun, was Sie möchten. Sie können z. B. ein neues IServiceBehaviorhinzufügen:

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

Dieser Ansatz ist nicht wiederverwendbar. Der Code, der die Beschreibung bearbeitet, wird in das Hostprogramm (in diesem Fall die Main()-Funktion codiert, sodass es schwierig ist, diese Logik in anderen Kontexten wiederzuverwenden. Es gibt auch andere Möglichkeiten zum Hinzufügen eines IServiceBehavior Elements, das keinen imperativen Code erfordert. Sie können ein Attribut von ServiceBehaviorAttribute ableiten und auf Ihren Dienstimplementierungstyp übernehmen, oder Sie können ein benutzerdefiniertes Verhalten konfigurierbar machen und es mithilfe der Konfiguration dynamisch zusammenstellen.

Eine leichte Variante des Beispiels kann jedoch auch verwendet werden, um dieses Problem zu lösen. Ein Ansatz besteht darin, den Code zu verschieben, der den ServiceBehavior aus Main() herausnimmt und in die OnOpening Methode einer benutzerdefinierten Ableitung von ServiceHost einfügt.

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

Dann können Sie innerhalb von Main() verwenden:

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

Jetzt haben Sie die benutzerdefinierte Logik in eine saubere Abstraktion gekapselt, die einfach in vielen verschiedenen Host-ausführbaren Dateien wiederverwendet werden kann.

Es ist nicht unmittelbar einsichtig, wie diese benutzerdefinierte ServiceHost-Klasse innerhalb von IIS (Internetinformationsdiensten) oder WAS (Windows Process Activation Service) verwendet werden kann. Diese Umgebungen unterscheiden sich von der Selbst-Hosting-Umgebung, da die Hostumgebung das ServiceHost im Auftrag der Anwendung instanziert. Die IIS- und WAS-Hostinginfrastruktur kennt nichts über Ihre benutzerdefinierte ServiceHost Ableitung.

ServiceHostFactory wurde dafür konzipiert, dieses Problem des Zugriffs auf Ihre benutzerdefinierte ServiceHost-Klasse durch IIS oder WAS zu lösen. Da ein benutzerdefinierter Host, der von ServiceHost abgeleitet ist, dynamisch konfiguriert und potenziell von verschiedenen Typen ist, wird die Hostingumgebung ihn nie direkt instanziieren. Stattdessen verwendet WCF ein Factorymuster, um eine Dereferenzierungsschicht zwischen der Hostumgebung und dem konkreten Typ des Diensts bereitzustellen. Falls Sie nichts anderes angeben, wird eine Standardimplementierung von ServiceHostFactory verwendet, die eine Instanz von ServiceHost zurückgibt. Sie können aber auch Ihre eigene Factory bereitstellen, die Ihren abgeleiteten Host zurückgibt, indem Sie den CLR-Typnamen Ihrer Factoryimplementierung in der @ServiceHost Direktive angeben.

Die Absicht ist, dass die Implementierung Ihrer eigenen Fabrik für grundlegende Fälle eine unkomplizierte Aufgabe sein sollte. Hier ist beispielsweise ein benutzerdefinierter ServiceHostFactory, der ein abgeleitetes ServiceHost zurückgibt.

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

Wenn Sie diese Factory anstelle der Standardfactory verwenden möchten, geben Sie den Typnamen in der @ServiceHost Direktive wie folgt an:

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

Zwar gibt es keine technische Grenze für das, was Sie mit einer von ServiceHost zurückgegebenen CreateServiceHost-Klasse tun können, jedoch wird empfohlen, die Implementierung der Factory so einfach wie möglich zu halten. Wenn Sie über viele benutzerdefinierte Logik verfügen, empfiehlt es sich, diese Logik in Den Host anstatt innerhalb der Factory zu platzieren, damit sie wiederverwendbar sein kann.

Es gibt eine weitere Ebene für die Hosting-API, die hier erwähnt werden sollte. WCF hat ServiceHostBase und ServiceHostFactoryBase, von denen ServiceHost bzw. ServiceHostFactory abgeleitet sind. Diese sind für komplexere Szenarien vorhanden, in denen Sie große Teile des Metadatensystems mit Ihren eigenen angepassten Kreationen austauschen müssen.