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 というクラスもあり、ServiceHost と ServiceHostFactory はそれぞれ、これらのクラスから派生します。 これらは、メタデータ システムの大部分がカスタム コードに置き換わるような、高度なシナリオを想定して用意されています。