配置和元数据支持

本主题介绍如何为绑定和绑定元素启用配置和元数据支持。

配置和元数据概述

本主题讨论以下任务,这些任务是 开发频道 任务列表中的可选项 1、2 和 4。

  • 为绑定元素启用配置文件支持。

  • 启用配置文件对绑定的支持。

  • 为绑定元素导出 WSDL 和策略断言。

  • 标识 WSDL 和策略断言以插入或配置你的绑定或绑定元素。

有关创建用户定义的绑定和绑定元素的信息,请参阅分别 创建 User-Defined 绑定创建 BindingElement

添加配置支持

若要为通道启用配置文件支持,必须实现两个配置节,System.ServiceModel.Configuration.BindingElementExtensionElement该部分支持绑定元素的配置支持,以及System.ServiceModel.Configuration.StandardBindingElementSystem.ServiceModel.Configuration.StandardBindingCollectionElement<TStandardBinding,TBindingConfiguration>启用对绑定的配置支持。

执行此作的一种更简单方法是使用 ConfigurationCodeGenerator 示例工具为绑定和绑定元素生成配置代码。

扩展 BindingElementExtensionElement

以下示例代码取自 Transport:UDP 示例。 UdpTransportElement 是一个 BindingElementExtensionElement,它向配置系统公开 UdpTransportBindingElement。 使用一些基本替代,该示例定义配置节名称、绑定元素的类型以及如何创建绑定元素。 然后,用户可以在配置文件中注册扩展部分,如下所示。

<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>  

为绑定添加配置

SampleProfileUdpBindingCollectionElement 节是一个 StandardBindingCollectionElement<TStandardBinding,TBindingConfiguration>,它向配置系统公开 SampleProfileUdpBinding。 批量实现委派给从 SampleProfileUdpBindingConfigurationElement 派生的 StandardBindingElementSampleProfileUdpBindingConfigurationElement 具有与 SampleProfileUdpBinding 上的属性对应的属性,以及从 ConfigurationElement 绑定映射的函数。 最后,OnApplyConfiguration 方法在 SampleProfileUdpBinding 中被重写,如下面的示例代码所示。

protected override void OnApplyConfiguration(string configurationName)  
{  
            if (binding == null)  
                throw new ArgumentNullException("binding");  
  
            if (binding.GetType() != typeof(SampleProfileUdpBinding))  
            {  
                var expectedType = typeof(SampleProfileUdpBinding).AssemblyQualifiedName;
                var typePassedIn = binding.GetType().AssemblyQualifiedName;
                throw new ArgumentException($"Invalid type for binding. Expected type: {expectedType}. Type passed in: {typePassedIn}.");  
            }  
            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 元数据实用工具工具(Svcutil.exe) 等工具生成绑定元素的客户端。

添加 WSDL 支持

绑定中的传输绑定元素负责在元数据中导出和导入寻址信息。 使用 SOAP 绑定时,传输绑定元素还应在元数据中导出正确的传输 URI。 以下示例代码取自 Transport:UDP 示例。

WSDL 导出

若要导出寻址信息,请 UdpTransportBindingElement 实现 System.ServiceModel.Description.IWsdlExportExtension 接口。 该方法 IWsdlExportExtension.ExportEndpoint 将正确的寻址信息添加到 WSDL 端口。

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

UdpTransportBindingElement 终结点使用 SOAP 绑定时,该方法的 ExportEndpoint 实现还会导出传输 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" />  
        </wsdlImporters>  
      </metadata>  
    </client>  
  </system.serviceModel>  
</configuration>  

运行 Svcutil.exe时,有两个选项可用于获取 Svcutil.exe 来加载 WSDL 导入扩展:

  1. 使用 /SvcutilConfig:<file> 使 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

IPolicyExportExtension.ExportPolicy 中,如果通道处于多路广播模式,添加 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));  
}  

由于自定义传输绑定元素负责处理寻址,因此在System.ServiceModel.Description.IPolicyExportExtension上的UdpTransportBindingElement实现还必须处理导出相应的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>  

然后,我们从已注册的类(System.ServiceModel.Description.IPolicyImportExtension)实现UdpBindingElementImporter。 在 IPolicyImportExtension.ImportPolicy 中,检查相应命名空间中的断言,并处理那些用于生成传输和检查是否为多播的断言。 此外,从绑定断言列表中删除导入程序处理的断言。 同样,在运行 Svcutil.exe时,有两个选项可用于集成:

  1. 使用 /SvcutilConfig:<file> 使 Svcutil.exe 指向配置文件。

  2. 将配置节添加到与 Svcutil.exe 处于同一目录的 Svcutil.exe.config 中。

添加自定义标准绑定导入程序

默认情况下,Svcutil.exe 和 System.ServiceModel.Description.WsdlImporter 类型识别和导入系统提供的绑定。 否则,绑定将作为 System.ServiceModel.Channels.CustomBinding 实例被导入。 若要启用 Svcutil.exe 和 WsdlImporter 以导入 SampleProfileUdpBindingUdpBindingElementImporter 还需充当自定义标准绑定导入程序。

自定义标准绑定导入程序在ImportEndpoint接口上实现System.ServiceModel.Description.IWsdlImportExtension方法,以检查从元数据导入的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;  
        }  
    }  
}  

通常,实现自定义标准绑定导入程序涉及检查导入的绑定元素的属性,以验证只有标准绑定可能设置的属性已更改,所有其他属性都是其默认值。 实现标准绑定导入程序的基本策略是创建标准绑定的实例,将绑定元素中的属性传播到标准绑定支持的标准绑定实例,并将标准绑定中的绑定元素与导入的绑定元素进行比较。