動作を使用したランタイムの構成と拡張
動作を使用すると、既定の動作を変更したり、カスタム拡張機能を追加したりできます。カスタム拡張機能では、サービス構成の検査および検証や、Windows Communication Foundation (WCF) クライアント アプリケーションとサービス アプリケーションのランタイム動作の変更を行います。 ここでは、動作インターフェイスとその実装方法について説明します。また、動作インターフェイスをサービスの説明 (サービス アプリケーションの場合) またはエンドポイント (クライアント アプリケーションの場合) にプログラムによって追加する方法と、構成ファイル内で追加する方法についても説明します。 システム指定の動作の使用の詳細については、「サービス ランタイム動作の指定」および「クライアント ランタイム動作の指定」を参照してください。
動作
動作の型は、Windows Communication Foundation (WCF) がサービス説明オブジェクト (サービスの場合) またはサービス エンド ポイント説明オブジェクト (クライアントの場合) を使用してランタイムを作成する前に、これらのオブジェクトに追加されます。このランタイムは、WCF サービスまたは WCF クライアントを実行します。 ランタイムの構築プロセスでこれらの動作を呼び出すと、コントラクト、バインディング、およびアドレスによって構築されたランタイムを変更するランタイム プロパティやランタイム メソッドにアクセスできます。
動作メソッド
すべての動作で、AddBindingParameters
メソッド、ApplyDispatchBehavior
メソッド、Validate
メソッド、および ApplyClientBehavior
メソッドを使用できます。ただし、IServiceBehavior には、例外が 1 つあります。ApplyClientBehavior
はクライアントで実行できないため、このメソッドを実装していません。
カスタム オブジェクトを変更したり、ランタイム構築時に使用するためにカスタム バインディングがアクセスできるコレクションにカスタム オブジェクトを追加したりするには、
AddBindingParameters
メソッドを使用します。 たとえば、これによって、チャネルを構築する方法に影響するが、チャネル開発者には知られていない保護要件を指定します。説明ツリーと対応するランタイム オブジェクトを検査し、特定の基準セットに従っていることを確認するには、
Validate
メソッドを使用します。説明ツリーを検査し、サービスまたはクライアントの特定のスコープのランタイムを変更するには、
ApplyDispatchBehavior
メソッドとApplyClientBehavior
メソッドを使用します。 また、拡張オブジェクトを挿入することもできます。Note
これらのメソッドでは説明ツリーが提供されますが、説明ツリーは検査にのみ使用します。 説明ツリーを変更すると、動作は未定義の状態になります。
変更できるプロパティと実装できるカスタマイズ インターフェイスには、サービスおよびクライアントのランタイム クラスからアクセスできます。 サービス型は、DispatchRuntime クラスと DispatchOperation クラスです。 クライアント型は、ClientRuntime クラスと ClientOperation クラスです。 ClientRuntime クラスと DispatchRuntime クラスは、それぞれクライアント全体またはサービス全体のランタイム プロパティと拡張コレクションにアクセスするための拡張エントリ ポイントです。 同様に、ClientOperation クラスと DispatchOperation クラスは、それぞれクライアント操作またはサービス操作のランタイム プロパティと拡張コレクションを公開します。 ただし、必要に応じて、操作ランタイム オブジェクトからより広いスコープのランタイム オブジェクトにアクセスできます。また、逆の場合も同様です。
Note
クライアントの実行動作を変更する際に使用できるランタイム プロパティと拡張型の詳細については、「クライアントの拡張」を参照してください。 サービス ディスパッチャーの実行動作を変更する際に使用できるランタイム プロパティと拡張型の詳細については、「ディスパッチャーの拡張」を参照してください。
ほとんどの WCF ユーザーは、ランタイムと直接やり取りすることはありません。代わりに、構成ファイル内のクラスや動作で、コア プログラミング モデルの構成要素 (エンドポイント、コントラクト、バインディング、アドレス、動作属性など) を使用します。 これらの要素によって説明ツリーが構成されます。説明ツリーは、このツリーで示されるサービスまたはクライアントをサポートするランタイムを構築するための完全な仕様を表します。
WCF には、次の 4 種類の動作があります。
サービスの動作 (IServiceBehavior 型) : ServiceHostBase を含むサービス ランタイム全体のカスタマイズを実現します。
エンドポイントの動作 (IEndpointBehavior 型) : サービス エンドポイントと、関連する EndpointDispatcher オブジェクトのカスタマイズを実現します。
コントラクトの動作 (IContractBehavior 型) : ClientRuntime クラス (クライアント アプリケーションの場合) と、DispatchRuntime クラス (サービス アプリケーションの場合) のカスタマイズを実現します。
操作の動作 (IOperationBehavior 型) : ClientOperation クラス (クライアントの場合) と、DispatchOperation クラス (サービスの場合) のカスタマイズを実現します。
カスタム属性を実装するか、アプリケーション構成ファイルを使用することにより、これらの動作をさまざまな説明オブジェクトに追加できます。また、適切な説明オブジェクトの動作コレクションに直接追加することもできます。 ただし、ICommunicationObject.Open または ServiceHost で ChannelFactory<TChannel> を呼び出す前に、サービス説明オブジェクトまたはサービス エンドポイント説明オブジェクトに追加する必要があります。
動作のスコープ
4 種類の動作があり、それぞれランタイム アクセスの特定のスコープに対応しています。
サービスの動作
IServiceBehavior を実装するサービスの動作は、サービス ランタイム全体を変更する主要機構です。 サービスの動作をサービスに追加する場合、3 つの方法があります。
サービス クラスの属性を使用する方法。 ServiceHost を構築すると、ServiceHost 実装は、リフレクションを使用してそのサービス型の属性セットを検出します。 これらの属性のいずれかが IServiceBehavior の実装である場合、ServiceDescription の動作コレクションに追加されます。 これにより、これらの動作はサービス ランタイムの構築に参加できます。
プログラムによって、ServiceDescription の動作コレクションに動作を追加する方法。 これを行うには、次のコード行を使用します。
ServiceHost host = new ServiceHost(/* Parameters */); host.Description.Behaviors.Add(/* Service Behavior */);
構成を拡張するカスタムの BehaviorExtensionElement を実装する方法。 これにより、アプリケーション構成ファイルからサービスの動作を使用できるようになります。
WCF のサービスの動作の例としては、ServiceBehaviorAttribute 属性、ServiceThrottlingBehavior、ServiceMetadataBehavior 動作などがあります。
コントラクトの動作
IContractBehavior インターフェイスを実装するコントラクトの動作は、コントラクト全体にわたり、クライアント ランタイムとサービス ランタイムを拡張する際に使用します。
コントラクトの動作をコントラクトに追加する場合、2 つの方法があります。 1 つは、コントラクト インターフェイスで使用するカスタム属性を作成する方法です。 コントラクト インターフェイスを ServiceHost または ChannelFactory<TChannel> に渡すと、WCF はインターフェイスの属性を検査します。 属性のいずれかが IContractBehavior の実装である場合、そのインターフェイス用に作成された System.ServiceModel.Description.ContractDescription の動作コレクションに追加されます。
カスタム コントラクトの動作属性に System.ServiceModel.Description.IContractBehaviorAttribute を実装することもできます。 この場合、適用先に応じて動作は次のようになります。
•コントラクト インターフェイスに適用した場合。 この場合は、任意のエンドポイント内の該当の型のすべてのコントラクトに動作が適用され、WCF は、IContractBehaviorAttribute.TargetContract プロパティの値を無視します。
•サービス クラスに適用した場合。 この場合、動作はコントラクトが TargetContract プロパティの値であるエンドポイントにのみ適用されます。
•コールバック クラスに適用した場合。 この場合は、双方向クライアントのエンドポイントに動作が適用され、WCF は、TargetContract プロパティの値を無視します。
2 番目の方法として、ContractDescription の動作コレクションに動作を追加する方法があります。
WCF のコントラクトの動作の例には、System.ServiceModel.DeliveryRequirementsAttribute 属性などがあります。 詳細および例については、リファレンス トピックを参照してください。
エンドポイントの動作
IEndpointBehavior を実装するエンドポイントの動作は、特定のエンドポイントのサービス ランタイムまたはクライアント ランタイム全体を変更する主要機構です。
エンドポイントの動作をサービスに追加する場合、2 つの方法があります。
Behaviors プロパティに動作を追加する方法。
構成を拡張するカスタムの BehaviorExtensionElement を実装する方法。
詳細および例については、リファレンス トピックを参照してください。
操作の動作
IOperationBehavior インターフェイスを実装する操作の動作は、各操作のクライアント ランタイムとサービス ランタイムを拡張する際に使用します。
操作の動作を操作に追加する場合、2 つの方法があります。 1 つは、操作をモデル化するメソッドで使用するカスタム属性を作成する方法です。 ServiceHost または ChannelFactory に操作を追加すると、WCF により、その操作用に作成された OperationDescription の動作コレクションに、あらゆる IOperationBehavior 属性が追加されます。
2 番目の機構は、構成された OperationDescription の動作コレクションに動作を直接追加します。
WCF の操作の動作の例には、OperationBehaviorAttribute や TransactionFlowAttribute などがあります。
詳細および例については、リファレンス トピックを参照してください。
構成を使用した動作の作成
サービス、エンドポイント、およびコントラクトの動作は、コードまたは属性を使用して指定するように設計できます。アプリケーション構成ファイルまたは Web 構成ファイルを使用して構成できるのは、サービスの動作とエンドポイントの動作だけです。 属性を使用して動作を公開した場合、開発者は、実行時に追加、削除、または変更できない動作をコンパイル時に指定できます。 多くの場合、これはサービスの適切な操作のために常に必要となる動作に適しています (System.ServiceModel.ServiceBehaviorAttribute 属性に対するトランザクション関連のパラメーターなど)。 構成を使用して動作を公開すると、開発者はサービス展開者に動作の仕様と構成を委ねることができます。 これは、動作がオプション コンポーネント、または他の展開固有の構成 (サービスまたはサービスの特定の承認構成についてメタデータを公開するかどうかなど) である場合に適しています。
Note
企業のアプリケーション ポリシーを machine.config 構成ファイルに挿入し、これらの項目をロックダウンすることで、ポリシーを適用する構成をサポートする動作を使用することもできます。 説明と例については、「方法: 企業内のエンドポイントをロックダウンする」を参照してください。
構成を使用して動作を公開するには、開発者は BehaviorExtensionElement の派生クラスを作成し、その拡張を構成に登録する必要があります。
次のコード例は、IEndpointBehavior で BehaviorExtensionElement を実装する方法を示しています。
// BehaviorExtensionElement members
public override Type BehaviorType
{
get { return typeof(EndpointBehaviorMessageInspector); }
}
protected override object CreateBehavior()
{
return new EndpointBehaviorMessageInspector();
}
構成システムでカスタムの BehaviorExtensionElement を読み込むには、拡張として登録する必要があります。 上記のエンドポイントの動作の構成ファイルを次のコード例に示します。
<configuration>
<system.serviceModel>
<services>
<service
name="Microsoft.WCF.Documentation.SampleService"
behaviorConfiguration="metadataSupport"
>
<host>
<baseAddresses>
<add baseAddress="http://localhost:8080/ServiceMetadata" />
</baseAddresses>
</host>
<endpoint
address="/SampleService"
binding="wsHttpBinding"
behaviorConfiguration="withMessageInspector"
contract="Microsoft.WCF.Documentation.ISampleService"
/>
<endpoint
address="mex"
binding="mexHttpBinding"
contract="IMetadataExchange"
/>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="metadataSupport">
<serviceMetadata httpGetEnabled="true" httpGetUrl=""/>
</behavior>
</serviceBehaviors>
<endpointBehaviors>
<behavior name="withMessageInspector">
<endpointMessageInspector />
</behavior>
</endpointBehaviors>
</behaviors>
<extensions>
<behaviorExtensions>
<add
name="endpointMessageInspector"
type="Microsoft.WCF.Documentation.EndpointBehaviorMessageInspector, HostApplication, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null"
/>
</behaviorExtensions>
</extensions>
</system.serviceModel>
</configuration>
ここで、Microsoft.WCF.Documentation.EndpointBehaviorMessageInspector
は動作拡張型です。また、HostApplication
は、該当するクラスがコンパイルされているアセンブリの名前です。
評価順序
System.ServiceModel.ChannelFactory<TChannel> と System.ServiceModel.ServiceHost は、プログラミング モデルと記述からランタイムを構築します。 前述のように、動作は、サービス、エンドポイント、コントラクト、および操作でランタイムの構築プロセスを支援します。
ServiceHost は次の順序で動作を適用します。
サービス
コントラクト
エンドポイント
操作
動作のどのコレクション内でも、順序が保証されるというわけではありません。
ChannelFactory<TChannel> は次の順序で動作を適用します。
コントラクト
エンドポイント
操作
この場合も、動作のどのコレクション内でも、順序が保証されるというわけではありません。
プログラムによる動作の追加
System.ServiceModel.Description.ServiceDescription の CommunicationObject.OnOpening メソッドの後で、サービス アプリケーションの System.ServiceModel.ServiceHostBase の各プロパティを変更しないでください。 このメソッドの後で変更すると、ServiceHostBase.Credentials および AddServiceEndpoint
の ServiceHostBase プロパティや System.ServiceModel.ServiceHost メソッドなどの一部のメンバーは例外をスローします。 変更を許可するメンバーもありますが、結果は未定義の状態になります。
同様に、クライアントで、System.ServiceModel.Description.ServiceEndpoint の OnOpening 呼び出しの後で、System.ServiceModel.ChannelFactory 値を変更しないでください。 この呼び出しの後で変更すると、ChannelFactory.Credentials プロパティは例外をスローします。その他のクライアント記述値は、エラーを発生させずに変更できます。 ただし、結果は未定義の状態になります。
サービスとクライアントのどちらの場合も、CommunicationObject.Open の呼び出しの前に記述を変更することをお勧めします。
動作属性の継承ルール
4 種類の動作はすべて、属性 (サービスの動作とコントラクトの動作) を使用して設定できます。 属性はマネージド オブジェクトとメンバーで定義され、マネージド オブジェクトとメンバーは継承をサポートしているため、継承のコンテキストでの動作属性の機能を定義する必要があります。
大まかに言えば、特定のスコープ (サービス、コントラクト、操作など) については、そのスコープの継承階層内のすべての動作属性が適用されるという継承ルールになります。 同じ種類の 2 つの動作属性がある場合、最も多く派生された種類だけが使用されます。
サービスの動作
サービス クラスの場合、指定のクラスとその親のすべてのサービス動作属性が適用されます。 継承階層の複数の場所に同じ種類の属性が適用されている場合は、最も多く派生された種類が使用されます。
[ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Multiple)]
[AspNetCompatibilityRequirementsAttribute(
AspNetCompatibilityRequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
public class A { /* … */ }
[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)]
public class B : A { /* … */}
たとえば、上記の例では、最終的にサービス B は、InstanceContextMode が Single、AspNetCompatibilityRequirementsMode が Allowed、ConcurrencyMode が Single になります。 ConcurrencyMode が Single になるのは、サービス B の ServiceBehaviorAttribute 属性の方がサービス A よりも多く派生されているためです。
コントラクトの動作
コントラクトの場合、指定のインターフェイスとその親のすべてのコントラクト動作属性が適用されます。 継承階層の複数の場所に同じ種類の属性が適用されている場合は、最も多く派生された種類が使用されます。
操作の動作
指定の操作が既存の抽象操作または仮想操作をオーバーライドしない場合、継承ルールは適用されません。
操作が既存の操作をオーバーライドする場合は、その操作とその親のすべての操作動作属性が適用されます。 継承階層の複数の場所に同じ種類の属性が適用されている場合は、最も多く派生された種類が使用されます。