ServiceHostFactory を使用したホストの拡張

Windows Communication Foundation (WCF) でサービスをホストするための標準 ServiceHost API は、WCF アーキテクチャの拡張ポイントです。 ユーザーは、この ServiceHost の派生型として独自のホスト クラスを定義できます。通常は、OnOpening() を使用するために ServiceDescription をオーバーライドして、これにより、サービスを開く前に、強制的に既定のエンドポイントを追加したり、動作を変更することができます。

自己ホスト環境では、カスタムの ServiceHost を作成する必要はありません。ホストをインスタンス化し、インスタンス化の後で Open() を呼び出すコードを記述するので、 この 2 つのステップの間に任意の処理を記述できます。 たとえば、新しい IServiceBehavior を次のように追加できます。

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

この方法は再利用できません。 説明を操作するコードはホスト プログラム (この場合は Main() 関数) に記述されているので、このロジックを別のコンテキストで使用するのは困難です。 このような強制コードを記述することなく、IServiceBehavior を追加する方法もあります。 ServiceBehaviorAttribute から派生した属性をサービス実装型に組み込む方法や、カスタム動作の詳細を構成できるようにしておき、構成を使用して動的に組み込む方法が考えられます。

ただし、サンプル コードを少し修正して問題を解決することもできます。 1 つの方法として、ServiceBehavior を追加するコードを Main() 内に記述する代わりに、OnOpening から派生した ServiceHost メソッドに記述することができます。

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

Main() 内には、次のように記述できます。

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

このようにカスタム ロジックをカプセル化、抽象化すると、さまざまなホスト アプリケーションで再利用できます。

カスタムの ServiceHost を Internet Information Services (IIS) や Windows Process Activation Service (WAS) で使用する方法は、それほど単純ではありません。 アプリケーションの代わりにホスティング環境が ServiceHost をインスタンス化するという点で、これらの環境は、自己ホスト環境と異なっています。 IIS および WAS ホスティング インフラストラクチャは、ServiceHost のカスタム派生物については何も認識しません。

ServiceHostFactory は、独自に定義した ServiceHost の派生クラスに、IIS または WAS からアクセスする手段として設計されました。 ServiceHost から派生したカスタム ホストは、動的に構成され、種類もさまざまであるため、ホスト環境でこれを直接インスタンス化することはありません。 代わりに、WCF は "ファクトリ パターン" を使用して、ホスティング環境と、サービスの具体的な型との間に間接レイヤーを提供します。 特に指定しなければ、ServiceHostFactory のインスタンスを返す、ServiceHost の既定の実装が使用されます。 ただし、ファクトリ実装の CLR 型名を @ServiceHost ディレクティブに指定して、派生ホストを返す独自のファクトリを提供できます。

基本的なケースでは、独自のファクトリは容易に実装できます。 派生 ServiceHostFactory を返す、カスタムの ServiceHost の例を次に示します。

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

既定のファクトリの代わりにこのファクトリを使用するには、@ServiceHost ディレクティブに、次のように型名を記述します。

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

ServiceHost から返す CreateServiceHost で行う処理について、技術的には制限はありませんが、ファクトリ実装はできるだけ単純にしておくことをお勧めします。 カスタム ロジックが多い場合は、ファクトリ内ではなく、ホスト側に記述して、ファクトリを再利用できるようにしておきます。

ここで、ホスティング API にはもう 1 つのレイヤーがあることを知っておく必要があります。 WCF には、ServiceHostBase および ServiceHostFactoryBase というクラスもあり、ServiceHostServiceHostFactory はそれぞれ、これらのクラスから派生します。 これらは、メタデータ システムの大部分がカスタム コードに置き換わるような、高度なシナリオを想定して用意されています。