メタデータ アーキテクチャの概要
Windows Communication Foundation (WCF) には、サービス メタデータをエクスポート、公開、取得、およびインポートするための高度なインフラストラクチャが用意されています。 WCF サービスでは、メタデータを使用してサービスのエンドポイントとの対話方法を記述し、Svcutil.exe などのツールでサービスにアクセスするためのクライアント コードを自動的に生成できるようにします。
WCF メタデータ インフラストラクチャを構成するほとんどの型が、System.ServiceModel.Description 名前空間に存在します。
WCF では、ServiceEndpoint クラスを使用して、サービス内のエンドポイントを記述します。 WCF を使用すると、サービス エンドポイント用のメタデータを生成したり、サービス メタデータをインポートして ServiceEndpoint インスタンスを生成したりできます。
WCF は、MetadataSet 型のインスタンスとしてサービスのメタデータを表現します。その構造は、WS-MetadataExchange で定義されているメタデータのシリアル化形式に強く関連付けられています。 MetadataSet 型は、Web サービス記述言語 (WSDL: Web Services Description Language) ドキュメント、XML スキーマ ドキュメント、WS-Policy 表現などの実際のサービス メタデータを MetadataSection インスタンスのコレクションとしてバンドルします。 各 System.ServiceModel.Description.MetadataSection インスタンスには、特定のメタデータ言語と識別子が含まれます。 System.ServiceModel.Description.MetadataSection はその MetadataSection.Metadata プロパティに、次のアイテムを含むことができます。
生のメタデータ。
MetadataReference のインスタンス。
MetadataLocation のインスタンス。
System.ServiceModel.Description.MetadataReference インスタンスは別のメタデータ交換 (MEX) エンドポイントをポイントし、System.ServiceModel.Description.MetadataLocation インスタンスは HTTP URL を使用してメタデータ ドキュメントをポイントします。 WCF では、WSDL ドキュメントを使用して、サービスで実装するサービス エンドポイント、サービス コントラクト、バインディング、メッセージ交換パターン、メッセージ、およびエラー メッセージを記述できます。 サービスで使用されるデータ型は、XML スキーマを使用して WSDL ドキュメントに記述されます。 詳細については、「スキーマのインポートとエクスポート」を参照してください。 WCF を使用すると、サービス動作、コントラクト動作、バインディング要素などの WSDL 拡張をエクスポートおよびインポートできます。このため、サービスの機能が拡張されます。 詳細については、「WCF 拡張に対するカスタム メタデータのエクスポート」を参照してください。
サービス メタデータのエクスポート
WCF では、"メタデータのエクスポート" は、サービス エンドポイントを説明したり、それらを対応する標準化表現に投影したりするプロセスです。クライアントは、これを利用してサービスの使用方法を理解します。 メタデータを ServiceEndpoint インスタンスからエクスポートするには、MetadataExporter 抽象クラスの実装を使用します。 System.ServiceModel.Description.MetadataExporter の実装によって、MetadataSet インスタンスにカプセル化されたメタデータが生成されます。
System.ServiceModel.Description.MetadataExporter クラスには、エンドポイント バインディングの機能と要件、エンドポイントに関連付けられた処理、メッセージ、エラーを記述するポリシー式を生成するためのフレームワークが用意されています。 これらのポリシー式は、PolicyConversionContext インスタンスにキャプチャされます。 System.ServiceModel.Description.MetadataExporter を実装すると、生成したメタデータにこれらのポリシー式を結び付けることができます。
System.ServiceModel.Description.MetadataExporter は、System.ServiceModel.Channels.BindingElement オブジェクトを IPolicyExportExtension の実装で使用するために生成するときに、ServiceEndpoint のバインディングで PolicyConversionContext インターフェイスを実装する各 System.ServiceModel.Description.MetadataExporter を呼び出します。 IPolicyExportExtension 型のカスタム実装の BindingElement インターフェイスを実装することで、新規のポリシー アサーションをエクスポートできます。
WsdlExporter 型は、WCF に含まれる System.ServiceModel.Description.MetadataExporter 抽象クラスの実装です。 WsdlExporter 型は、結び付けられたポリシー式を使用して WSDL メタデータを生成します。
サービス エンドポイントでのエンドポイント動作、コントラクト動作、またはバインド要素のカスタム WSDL メタデータまたは WSDL 拡張をエクスポートするには、IWsdlExportExtension インターフェイスを実装する必要があります。 WsdlExporter は WSDL ドキュメントの生成時に、ServiceEndpoint インターフェイスを実装するバインディング要素、処理動作、コントラクト動作、およびエンドポイント動作の IWsdlExportExtension インスタンスを参照します。
サービス メタデータの公開
WCF サービスでは、1 つ以上のメタデータ エンドポイントを公開することにより、メタデータを公開します。 サービス メタデータを公開すると、サービス メタデータで MEX や HTTP/GET 要求などの標準化プロトコルを使用できるようになります。 メタデータ エンドポイントは、アドレス、バインディング、およびコントラクトを持つという点で、他のサービス エンドポイントと似ています。 メタデータ エンドポイントは、構成またはコードを使用してサービス ホストに追加できます。
WCF サービスのメタデータ エンドポイントを公開するには、最初に ServiceMetadataBehavior サービス動作のインスタンスをサービスに追加する必要があります。 サービスに System.ServiceModel.Description.ServiceMetadataBehavior インスタンスを追加することによって、1 つ以上のメタデータ エンドポイントを公開することでメタデータを公開する機能がサービスに追加されます。 System.ServiceModel.Description.ServiceMetadataBehavior サービス動作を追加すると、MEX プロトコルをサポートするメタデータ エンドポイント、または HTTP/GET 要求に応答するメタデータ エンドポイントを公開できます。
MEX プロトコルを使用するメタデータ エンドポイントを追加するには、IMetadataExchange という名前のサービス コントラクトを使用するサービス エンドポイントをサービス ホストに追加します。WCF により、このサービス コントラクト名を持つ IMetadataExchange インターフェイスが定義されます。 WS-MetadataExchange のエンドポイント、つまり MEX エンドポイントでは、MetadataExchangeBindings クラスで静的ファクトリ メソッドによって公開される 4 つの既定のバインディングの 1 つを使用して、WCF ツール (Svcutil.exe など) によって使用される既定のバインディングを照合できます。 また、カスタム バインドを使用して MEX メタデータ エンドポイントを構成することもできます。
ServiceMetadataBehavior は System.ServiceModel.Description.WsdlExporter を使用して、サービス内のすべてのサービス エンドポイント用のメタデータをエクスポートします。 サービスからメタデータをエクスポートする方法の詳細については、「メタデータのエクスポートとインポート」を参照してください。
ServiceMetadataBehavior は、ServiceMetadataExtension インスタンスを拡張としてサービス ホストに追加することで、サービス ホストを拡張します。 System.ServiceModel.Description.ServiceMetadataExtension により、メタデータ公開プロトコルを実装することができます。 また、System.ServiceModel.Description.ServiceMetadataExtension を使用して、Metadata プロパティにアクセスすると、実行時にサービスのメタデータを取得できます。
注意事項
MEX エンドポイントをアプリケーション構成ファイルに追加した後で、ServiceMetadataBehavior をコード内のサービス ホストに追加しようとすると、次の例外が発生します。
System.InvalidOperationException: コントラクト名 'IMetadataExchange' は、サービス Service1 によって実装されたコントラクトの一覧に見つかりませんでした。 ServiceMetadataBehavior を構成ファイルまたは ServiceHost ディレクトリに直接追加してこのコントラクトのサポートを有効にしてください。
ServiceMetadataBehavior を構成ファイルに追加するか、またはエンドポイントと ServiceMetadataBehavior の両方をコードに追加することにより、この問題を回避できます。
アプリケーション構成ファイルへの ServiceMetadataBehavior の追加例については、入門に関するページを参照してください。 コードへの ServiceMetadataBehavior の追加例については、「自己ホスト」のサンプルを参照してください。
注意事項
それぞれに同じ名前の操作が含まれている 2 つ異なるサービス コントラクトを公開するサービスのメタデータを公開すると、例外がスローされます。 たとえば、Get(Car c) 操作を含む ICarService という名前のサービス コントラクトを公開するサービスがあり、その同じサービスが Get(Book b) 操作を含む IBookService という名前のサービス コントラクトを公開する場合、サービスのメタデータを生成するときに、例外がスローされるか、エラー メッセージが表示されます。 この問題を回避するには、次のいずれかの操作を実行します。
サービス メタデータの取得
WCF では、WS-MetadataExchange、HTTP などの標準化プロトコルを使用してサービス メタデータを取得できます。 これらのプロトコルはいずれも、MetadataExchangeClient 型でサポートされます。 アドレスとオプションのバインディングを提供することによって、System.ServiceModel.Description.MetadataExchangeClient 型を使用して、サービス メタデータを取得します。 System.ServiceModel.Description.MetadataExchangeClient インスタンスで使用するバインディングは、MetadataExchangeBindings 静的クラスの既定のバインディング、ユーザー指定のバインディング、IMetadataExchange
コントラクト用のエンドポイント構成から読み込まれたバインディングのいずれかです。 System.ServiceModel.Description.MetadataExchangeClient は同様に、HttpWebRequest 型を使用して、メタデータへの HTTP URL 参照を解決できます。
既定では、System.ServiceModel.Description.MetadataExchangeClient インスタンスは、1 つの ChannelFactoryBase インスタンスに結び付けられています。 ChannelFactoryBase によって使用される System.ServiceModel.Description.MetadataExchangeClient インスタンスは、GetChannelFactory 仮想メソッドをオーバーライドすることによって変更または置換することができます。 同様に、System.Net.HttpWebRequest 仮想メソッドをオーバーライドすることによって、HTTP/GET 要求を行うために System.ServiceModel.Description.MetadataExchangeClient が使用する MetadataExchangeClient.GetWebRequest インスタンスを変更または置換できます。
Svcutil.exe ツールを使用して /target:metadata スイッチとアドレスを渡すことにより、WS-MetadataExchange または HTTP/GET 要求を使用してサービス メタデータを取得できます。 Svcutil.exe は指定したアドレスでメタデータをダウンロードし、ディスクにファイルを保存します。 Svcutil.exe は、System.ServiceModel.Description.MetadataExchangeClient インスタンスを内部的に使用し、Svcutil.exe に渡されたアドレスのスキームに一致する名前を持つ MEX エンドポイント構成が存在する場合は、これをアプリケーション構成ファイルから読み込みます。 存在しない場合、Svcutil.exe は、MetadataExchangeBindings 静的ファクトリ型によって定義されたバインディングの 1 つを既定で使用します。
サービス メタデータのインポート
WCF では、メタデータのインポートとは、サービス、またはそのコンポーネントの抽象表現をメタデータから生成するプロセスです。 たとえば、WCF では、ServiceEndpoint インスタンス、Binding インスタンス、または ContractDescription インスタンスをサービスの WSDL ドキュメントからインポートできます。 WCF のサービス メタデータをインポートするには、MetadataImporter 抽象クラスの実装を使用します。 System.ServiceModel.Description.MetadataImporter クラスから派生した型では、WCF の WS-Policy インポート ロジックを利用したメタデータ形式のインポートがサポートされます。
System.ServiceModel.Description.MetadataImporter の実装は、PolicyConversionContext オブジェクトでサービス メタデータに結び付けられたポリシー表現を収集します。 その後、System.ServiceModel.Description.MetadataImporter は、IPolicyImportExtension プロパティ内の PolicyImportExtensions インターフェイスの実装を呼び出すことによって、メタデータのインポートの一部として、ポリシーを処理します。
System.ServiceModel.Description.MetadataImporter インスタンスの IPolicyImportExtension コレクションに PolicyImportExtensions インターフェイスの独自の実装を追加することによって、新しいポリシー アサーションをインポートするためのサポートを System.ServiceModel.Description.MetadataImporter に追加できます。 または、クライアント アプリケーション構成ファイルにポリシー インポート拡張を登録できます。
System.ServiceModel.Description.WsdlImporter 型は、WCF に含まれる System.ServiceModel.Description.MetadataImporter 抽象クラスの実装です。 System.ServiceModel.Description.WsdlImporter 型は、MetadataSet オブジェクトにまとめられた、結び付けられているポリシーを使用して WSDL メタデータをインポートします。
IWsdlImportExtension インターフェイスを実装し、この実装を WsdlImportExtensions インスタンスの System.ServiceModel.Description.WsdlImporter プロパティに追加することで、WSDL 拡張のインポートのサポートを追加できます。 System.ServiceModel.Description.WsdlImporter は、クライアント アプリケーション構成ファイルに登録された System.ServiceModel.Description.IWsdlImportExtension インターフェイスの実装を読み込むこともできます。
動的なバインド
エンドポイントのバインドが変化するイベントでサービス エンドポイントへのチャネルを作成する、または、同じコントラクトを使用しているがバインドが異なるエンドポイントへのチャネルを作成するために使用するバインドを動的に更新することができます。 MetadataResolver 静的クラスを使用して、特定のコントラクトを実装しているサービス エンドポイントのメタデータを、実行時に取得またはインポートできます。 その後、インポートした System.ServiceModel.Description.ServiceEndpoint オブジェクトを使用して、必要なエンドポイントに対するクライアントまたはチャネル ファクトリを作成できます。