次の方法で共有


構成とメタデータのサポート

ここでは、バインディングおよびバインディング要素用に構成とメタデータのサポートを有効にする方法を説明します。

構成とメタデータの概要

ここでは、次の作業について説明します。これは、チャネルの開発タスク リストのオプション項目 1.、2. および 4. に当たります。

  • バインディング要素の構成ファイル サポートを有効にします。
  • バインディングの構成ファイル サポートを有効にします。
  • バインディング要素の WSDL とポリシー アサーションをエクスポートします。
  • バインディングまたはバインディング要素に挿入して構成する WSDL とポリシー アサーションを特定します。

ユーザー定義バインディングおよびバインディング要素の作成の詳細については、それぞれ「ユーザー定義バインディングの作成」および「BindingElement の作成」を参照してください。

構成サポートの追加

チャネルに対する構成ファイルのサポートを有効にするには、2 つの構成セクションを実装する必要があります。1 つはバインディング要素に対する構成のサポートを有効にする System.ServiceModel.Configuration.BindingElementExtensionElement で、もう 1 つはバインディングに対する構成のサポートを有効にする System.ServiceModel.Configuration.StandardBindingElementSystem.ServiceModel.Configuration.StandardBindingCollectionElement です。

これを行う簡単な方法は、ConfigurationCodeGenerator サンプル ツールを使用して、バインディングおよびバインディング要素の構成コードを生成することです。

BindingElementExtensionElement の拡張

次のコード例は、Transport: UDP のサンプルから取られています。 ``UdpTransportElementUdpTransportBindingElement を構成システムに公開する BindingElementExtensionElement です。いくつかの基本的なオーバーライドを行うことで、サンプルでは構成セクション名、バインディング要素の種類とバインディング要素の作成方法が定義されます。その後、次のようにして拡張セクションを構成ファイルに登録できます。

<configuration>
  <system.serviceModel>
    <extensions>
      <bindingElementExtensions>
      <add name="udpTransport" type="Microsoft.ServiceModel.Samples.UdpTransportElement, UdpTransport />
      </bindingElementExtensions>
    </extensions>
  </system.serviceModel>
</configuration>

この拡張は、UDP をトランスポートとして使用するためにカスタム バインディングから参照されます。

<configuration>
  <system.serviceModel>
    <bindings>
      <customBinding>
       <binding configurationName="UdpCustomBinding">
         <udpTransport/>
       </binding>
      </customBinding>
    </bindings>
  </system.serviceModel>
</configuration>

バインディングの構成の追加

セクション ``SampleProfileUdpBindingCollectionElementStandardBindingCollectionElement で、SampleProfileUdpBinding を構成システムに公開します。実装の大部分は SampleProfileUdpBindingConfigurationElement で代行されます。これは StandardBindingElement の派生です。SampleProfileUdpBindingConfigurationElement には SampleProfileUdpBinding にあるプロパティに対応するプロパティがあり、ConfigurationElement バインディングからマップする関数があります。次のサンプル コードで示すように、最後に、OnApplyConfiguration メソッドが SampleProfileUdpBinding 内でオーバーライドされます。

protected override void OnApplyConfiguration(string configurationName)
{
            if (binding == null)
                throw new ArgumentNullException("binding");

            if (binding.GetType() != typeof(SampleProfileUdpBinding))
            {
                throw new ArgumentException(string.Format(CultureInfo.CurrentCulture,
                    "Invalid type for binding. Expected type: {0}. Type passed in: {1}.",
                    typeof(SampleProfileUdpBinding).AssemblyQualifiedName,
                    binding.GetType().AssemblyQualifiedName));
            }
            SampleProfileUdpBinding udpBinding = (SampleProfileUdpBinding)binding;

            udpBinding.OrderedSession = this.OrderedSession;
            udpBinding.ReliableSessionEnabled = this.ReliableSessionEnabled;
            udpBinding.SessionInactivityTimeout = this.SessionInactivityTimeout;
            if (this.ClientBaseAddress != null)
                   udpBinding.ClientBaseAddress = ClientBaseAddress;
}

このハンドラを構成システムに登録するには、次のセクションを関連する構成ファイルに追加します。

<configuration>
  <configSections>
     <sectionGroup name="system.serviceModel">
         <sectionGroup name="bindings">
                 <section name="sampleProfileUdpBinding" type="Microsoft.ServiceModel.Samples.SampleProfileUdpBindingCollectionElement, UdpTransport />
         </sectionGroup>
     </sectionGroup>
  </configSections>
</configuration>

これは <system.ServiceModel> 構成セクションから参照できます。

<configuration>
  <system.serviceModel>
    <client>
      <endpoint configurationName="calculator"
                address="soap.udp://localhost:8001/" 
                bindingConfiguration="CalculatorServer"
                binding="sampleProfileUdpBinding" 
                contract= "Microsoft.ServiceModel.Samples.ICalculatorContract">
      </endpoint>
    </client>
  </system.serviceModel>
</configuration>

バインディング要素のメタデータ サポートの追加

チャネルをメタデータ システムに統合するには、ポリシーのインポートとエクスポートの両方がサポートされている必要があります。これにより、ServiceModel Metadata Utility Tool (Svcutil.exe) などのツールでバインディング要素のクライアントを生成できます。

WSDL サポートの追加

バインディングのトランスポート バインディング要素は、メタデータのアドレス指定情報のインポートとエクスポートを行います。SOAP バインディングを使用する場合は、トランスポート バインディング要素によっても、メタデータの正しいトランスポート URI がエクスポートされます。次のコード例は、Transport: UDP のサンプルから取られています。

WSDL エクスポート

アドレス指定情報をエクスポートするには、UdpTransportBindingElementSystem.ServiceModel.Description.IWsdlExportExtension インターフェイスを実装します。System.ServiceModel.Description.IWsdlExportExtension.ExportEndpoint(System.ServiceModel.Description.WsdlExporter,System.ServiceModel.Description.WsdlEndpointConversionContext) メソッドにより、正しいアドレス指定情報が WSDL ポートに追加されます。

if (context.WsdlPort != null)
{
    AddAddressToWsdlPort(context.WsdlPort, context.Endpoint.Address, encodingBindingElement.MessageVersion.Addressing);
}

エンドポイントが SOAP バインディングを使用する場合、ExportEndpoint メソッドの UdpTransportBindingElement の実装でも、次のようにトランスポート URI がエクスポートされます。

WsdlNS.SoapBinding soapBinding = GetSoapBinding(context, exporter);
if (soapBinding != null)
{
    soapBinding.Transport = UdpPolicyStrings.UdpNamespace;
}

WSDL インポート

WSDL インポート システムを拡張してアドレスのインポートを処理するには、次の構成を Svcutil.exe の構成ファイルに追加する必要があります。Svcutil.exe.config ファイルの次の例を参照してください。

<configuration>
  <system.serviceModel>
    <client>
      <metadata>
        <wsdlImporters>
          <extension type=" Microsoft.ServiceModel.Samples.UdpBindingElementImporter, UdpTransport" />
        </policyImporters>
      </metadata>
    </client>
  </system.serviceModel>
</configuration>

Svcutil.exe を実行する場合、Svcutil.exe に WSDL インポートの拡張を読み込ませるために次の 2 つのオプションがあります。

  1. /SvcutilConfig:<ファイル名> を使用して、Svcutil.exe に構成ファイルを指定します。
  2. Svcutil.exe と同じディレクトリにある Svcutil.exe.config に構成セクションを追加します。

UdpBindingElementImporter 型は System.ServiceModel.Description.IWsdlImportExtension インターフェイスを実装します。ImportEndpoint メソッドは、次のようにして WSDL ポートからアドレスをインポートします。

BindingElementCollection bindingElements = context.Endpoint.Binding.CreateBindingElements();
TransportBindingElement transportBindingElement = bindingElements.Find<TransportBindingElement>();
if (transportBindingElement is UdpTransportBindingElement)
{
    ImportAddress(context);
}

ポリシー サポートの追加

カスタム バインディング要素では、WSDL バインディング内のポリシー アサーションをエクスポートして、サービス エンドポイントでそのバインディング要素の機能を表現します。次のコード例は、Transport: UDP のサンプルから取られています。

ポリシーのエクスポート

UdpTransportBindingElement 型はポリシーのエクスポートをサポートするために System.ServiceModel.Description.IPolicyExportExtension を実装します。その結果、System.ServiceModel.Description.MetadataExporter には、これを含む任意のバインディングでのポリシーの生成時に UdpTransportBindingElement が含まれます。

System.ServiceModel.Description.IPolicyExportExtension.ExportPolicy(System.ServiceModel.Description.MetadataExporter,System.ServiceModel.Description.PolicyConversionContext) では、UDP のアサーションを追加します。チャネルがマルチキャスト モードである場合は、別のアサーションを追加します。これは、マルチキャスト モードは通信スタックの構築方法に影響を与えるため、両方の側において調整される必要があるためです。

ICollection<XmlElement> bindingAssertions = context.GetBindingAssertions();
XmlDocument xmlDocument = new XmlDocument();
bindingAssertions.Add(xmlDocument.CreateElement(
UdpPolicyStrings.Prefix, UdpPolicyStrings.TransportAssertion, UdpPolicyStrings.UdpNamespace));
if (Multicast)
{
    bindingAssertions.Add(xmlDocument.CreateElement(
UdpPolicyStrings.Prefix, UdpPolicyStrings.MulticastAssertion,     UdpPolicyStrings.UdpNamespace));
}

カスタム トランスポート バインディング要素はアドレス指定の処理を実行するため、UdpTransportBindingElement への System.ServiceModel.Description.IPolicyExportExtension の実装でも、WS-Addressing ポリシー アサーションのエクスポートが処理されて、使用されている WS-Addressing のバージョンが示されます。

AddWSAddressingAssertion(context, encodingBindingElement.MessageVersion.Addressing);

ポリシーのインポート

ポリシー インポート システムを拡張するには、次の構成を Svcutil.exe の構成ファイルに追加する必要があります。Svcutil.exe.config ファイルの次の例を参照してください。

<configuration>
  <system.serviceModel>
    <client>
      <metadata>
        <policyImporters>
          <extension type=" Microsoft.ServiceModel.Samples.UdpBindingElementImporter, UdpTransport" />
        </policyImporters>
      </metadata>
    </client>
  </system.serviceModel>
</configuration>

次に、登録されたクラス (UdpBindingElementImporter) から System.ServiceModel.Description.IPolicyImportExtension を実装します。System.ServiceModel.Description.IPolicyImportExtension.ImportPolicy(System.ServiceModel.Description.MetadataImporter,System.ServiceModel.Description.PolicyConversionContext) で、適切な名前空間にあるアサーションを調べ、トランスポートを生成するためにそのアサーションを処理して、マルチキャストであるかどうかをチェックします。さらに、インポータが処理するアサーションをバインディング アサーションの一覧から削除します。Svcutil.exe を実行する場合、ここでも、統合用に次の 2 つのオプションがあります。

  1. /SvcutilConfig:<ファイル名> を使用して、Svcutil.exe に構成ファイルを指定します。
  2. Svcutil.exe と同じディレクトリにある Svcutil.exe.config に構成セクションを追加します。

カスタムの標準バインディング インポータの追加

Svcutil.exe と System.ServiceModel.Description.WsdlImporter 型は、既定でシステム指定のバインディングを識別してインポートします。これ以外の場合、バインディングは、System.ServiceModel.Channels.CustomBinding インスタンスとしてインポートされます。Svcutil.exe と WsdlImporter を有効にして SampleProfileUdpBinding をインポートする場合、UdpBindingElementImporter もカスタムの標準バインディング インポータとして機能します。

カスタムの標準バインディング インポータは、System.ServiceModel.Description.IWsdlImportExtension インターフェイスに ImportEndpoint メソッドを実装しており、メタデータからインポートされた System.ServiceModel.Channels.CustomBinding インスタンスを調べて、これが特定の標準バインディングによって生成されたものであるかどうかを判別できます。

if (context.Endpoint.Binding is CustomBinding)
{
    Binding binding;
    if (transportBindingElement is UdpTransportBindingElement)
    {
        //if TryCreate is true, the CustomBinding will be replace by a SampleProfileUdpBinding in the
        //generated config file for better typed generation.
        if (SampleProfileUdpBinding.TryCreate(bindingElements, out binding))
        {
            binding.Name = context.Endpoint.Binding.Name;
            binding.Namespace = context.Endpoint.Binding.Namespace;
            context.Endpoint.Binding = binding;
        }
    }
}

一般に、カスタムの標準バインディング インポータを実装すると、インポートしたバインディング要素のプロパティを調べて、標準バインディングによって設定されたプロパティのみが変更され、その他のすべてのプロパティは既定のままであることが検証されます。標準バインディング インポータを実装する場合の基本的な方法は、標準バインディングのインスタンスを作成し、標準バインディングがサポートするバインディング要素のプロパティを標準バインディング インスタンスに反映し、標準バインディングのバインディング要素とインポートしたバインディング要素とを比較します。