Поделиться через


Конфигурация и поддержка метаданных

В этом разделе описывается, как включить поддержку конфигурации и метаданных для привязки и элементов привязки.

Общие сведения о конфигурации и метаданных

В этом разделе рассматриваются следующие задачи, которые являются необязательными элементами 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

Для экспорта сведений об адресации реализуется UdpTransportBindingElementSystem.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:

  1. Наведите Svcutil.exe в файл конфигурации с помощью файла /SvcutilConfig:<file>.

  2. добавить раздел конфигурации в файл 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 существует два варианта интеграции:

  1. Наведите Svcutil.exe в файл конфигурации с помощью файла /SvcutilConfig:<file>.

  2. добавить раздел конфигурации в файл 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;  
        }  
    }  
}  

Как правило, реализация пользовательского импортера стандартной привязки предусматривает проверку свойств импортированных элементов привязки на предмет того, что изменены только свойства, которые могли быть заданы стандартной привязкой, а все остальные свойства имеют значения по умолчанию. Простейшая стратегия для реализации импортера стандартной привязки - создать экземпляр стандартной привязки, распространить на экземпляр стандартной привязки свойства из элементов привязки, поддерживаемые стандартной привязкой, и затем сравнить элементы привязки из стандартной привязки с импортированными элементами привязки.