本主题介绍如何为绑定和绑定元素启用配置和元数据支持。
配置和元数据概述
本主题讨论以下任务,这些任务是 开发频道 任务列表中的可选项 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
派生的 StandardBindingElement。
SampleProfileUdpBindingConfigurationElement
具有与 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 导入扩展:
使用 /SvcutilConfig:<file> 使 Svcutil.exe 指向配置文件。
将配置节添加到与 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时,有两个选项可用于集成:
使用 /SvcutilConfig:<file> 使 Svcutil.exe 指向配置文件。
将配置节添加到与 Svcutil.exe 处于同一目录的 Svcutil.exe.config 中。
添加自定义标准绑定导入程序
默认情况下,Svcutil.exe 和 System.ServiceModel.Description.WsdlImporter 类型识别和导入系统提供的绑定。 否则,绑定将作为 System.ServiceModel.Channels.CustomBinding 实例被导入。 若要启用 Svcutil.exe 和 WsdlImporter 以导入 SampleProfileUdpBinding
,UdpBindingElementImporter
还需充当自定义标准绑定导入程序。
自定义标准绑定导入程序在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;
}
}
}
通常,实现自定义标准绑定导入程序涉及检查导入的绑定元素的属性,以验证只有标准绑定可能设置的属性已更改,所有其他属性都是其默认值。 实现标准绑定导入程序的基本策略是创建标准绑定的实例,将绑定元素中的属性传播到标准绑定支持的标准绑定实例,并将标准绑定中的绑定元素与导入的绑定元素进行比较。