Конфигурация и поддержка метаданных
В этом разделе описывается, как включить поддержку конфигурации и метаданных для привязки и элементов привязки.
Общие сведения о конфигурации и метаданных
В этом разделе рассматриваются следующие задачи, которые являются необязательными элементами 1, 2 и 4 в списке задач "Разработка каналов ".
включение поддержки файла конфигурации для элемента привязки.
включение поддержки файла конфигурации для привязки;
экспорт WSDL-кода и утверждений политики для элемента привязки;
определение вставляемых WSDL-кода и утверждений политики и настройка привязки или элемента привязки.
Сведения о создании определяемых пользователем привязок и элементах привязки см. в разделе "Создание определяемых пользователем привязок" и "Создание привязки" соответственно.
Добавление поддержки конфигурации
Чтобы включить поддержку файла конфигурации для канала, необходимо реализовать два раздела конфигурации: System.ServiceModel.Configuration.BindingElementExtensionElement для поддержки конфигурации для элементов привязки и System.ServiceModel.Configuration.StandardBindingElement и System.ServiceModel.Configuration.StandardBindingCollectionElement<TStandardBinding,TBindingConfiguration> для поддержки конфигурации для привязок.
Для этого проще использовать пример средства ConfigurationCodeGenerator для создания кода конфигурации для привязок и элементов привязки.
Расширение класса BindingElementExtensionElement
Следующий пример кода взят из примера транспорта: 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 (универсальный код ресурса) транспорта. Следующий пример кода взят из примера транспорта: UDP .
Экспорт WSDL
Для экспорта сведений об адресации реализуется UdpTransportBindingElement
System.ServiceModel.Description.IWsdlExportExtension интерфейс. Метод IWsdlExportExtension.ExportEndpoint добавляет правильные сведения об адресации в порт WSDL.
if (context.WsdlPort != null)
{
AddAddressToWsdlPort(context.WsdlPort, context.Endpoint.Address, encodingBindingElement.MessageVersion.Addressing);
}
Реализация метода UdpTransportBindingElement
в элементе ExportEndpoint также экспортирует URI транспорта, когда конечная точка использует привязку SOAP:
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 существует два варианта обеспечить загрузку программой расширений импорта WSDL:
Наведите Svcutil.exe в файл конфигурации с помощью файла /SvcutilConfig:<file>.
добавить раздел конфигурации в файл Svcutil.exe.config, находящийся в том же каталоге, что и файл Svcutil.exe.
Тип 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 для конечной точки службы, чтобы показать возможности этого элемента привязки. Следующий пример кода взят из примера транспорта: 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 существует два варианта интеграции:
Наведите Svcutil.exe в файл конфигурации с помощью файла /SvcutilConfig:<file>.
добавить раздел конфигурации в файл Svcutil.exe.config, находящийся в том же каталоге, что и файл Svcutil.exe.
Добавление пользовательского импортера стандартной привязки
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;
}
}
}
Как правило, реализация пользовательского импортера стандартной привязки предусматривает проверку свойств импортированных элементов привязки на предмет того, что изменены только свойства, которые могли быть заданы стандартной привязкой, а все остальные свойства имеют значения по умолчанию. Простейшая стратегия для реализации импортера стандартной привязки - создать экземпляр стандартной привязки, распространить на экземпляр стандартной привязки свойства из элементов привязки, поддерживаемые стандартной привязкой, и затем сравнить элементы привязки из стандартной привязки с импортированными элементами привязки.