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


Пользовательские кодировщики

В данном разделе рассматривается процесс создания пользовательских кодировщиков.

В Windows Communication Foundation (WCF) используется привязка для указания способа передачи данных по сети между конечными точками. Привязка состоит из последовательности элементов привязки. Привязка включает необязательные элементы привязки протокола, такие как безопасность, обязательный элемент привязки кодировщика сообщений и обязательный элемент привязки транспорта. Кодировщик сообщений представлен элементом привязки кодирования сообщений. Три кодировщика сообщений включаются в WCF: двоичный механизм, механизм оптимизации передачи сообщений (MTOM) и текст.

Элемент привязки кодирования сообщений сериализует исходящее сообщение Message и передает его транспорту или получает сериализованную форму сообщения от транспорта и передает ее на уровень протоколов, если он имеется, или в приложение, если он отсутствует.

Кодировщики сообщений преобразовывают экземпляры Message в представление для передачи и наоборот. Хотя в описании кодировщиков указано, что они находятся над транспортным уровнем в стеке каналов, они располагаются на транспортном уровне. Транспорты (например, HTTP) форматируют сообщение в соответствии с требованиями стандарта транспортов. Кодировщики (например, Text Xml) только кодируют сообщение.

При подключении к ранее существующему клиенту или серверу не всегда имеется возможность выбрать определенное кодирование сообщений. Однако службы WCF можно сделать доступными через несколько конечных точек, каждый из которых имеет другой кодировщик сообщений. Если один кодировщик не охватывает всю аудиторию для службы, следует рассмотреть возможность представления службы через несколько конечных точек. Это позволит клиентским приложениям выбрать наиболее подходящую конечную точку. Использование нескольких конечных точек позволяет сочетать преимущества разных кодировщиков сообщений с другими элементами привязки.

Кодировщики, предоставляемые системой

WCF предоставляет несколько системных привязок, предназначенных для покрытия наиболее распространенных сценариев приложений. Каждая из этих привязок содержит транспорт, кодировщик сообщений и другие параметры (например, безопасность). В этом разделе описывается расширение Textкодировщиков сообщений Binaryи MTOM кодировщиков сообщений, включенных в WCF, или создание собственного пользовательского кодировщика. Кодировщик текстовых сообщений поддерживает как кодирование на простом языке XML, так и кодирование SOAP. Режим кодирования на простом языке XML кодировщика текстовых сообщений называется кодировщиком POX ("plain old XML"), что позволяет отличить его от текстового кодирования SOAP.

Дополнительные сведения о сочетаниях элементов привязки, предоставляемых системными привязками, см. в соответствующем разделе в разделе "Выбор транспорта".

Принцип работы с кодировщиками, предоставляемыми системой

Кодирование добавляется в привязку с помощью класса, унаследованного от класса MessageEncodingBindingElement.

WCF предоставляет следующие типы элементов привязки, производных от MessageEncodingBindingElement класса, который может предоставлять кодировку текстового, двоичного и механизма оптимизации передачи сообщений (MTOM):

  • TextMessageEncodingBindingElement. Кодировщик для сообщений XML с наиболее широкими возможностями взаимодействия, но при этом наименее неэффективный. Веб-служба или клиент веб-службы в общем могут понимать XML в текстовом виде. Однако передача больших блоков двоичных данных в виде текста неэффективна.

  • BinaryMessageEncodingBindingElement. Представляет собой элемент привязки, указывающий кодирование символов и управление версиями сообщений для сообщений XML в двоичном формате. Это наиболее эффективное из параметров кодирования, но наименьшее взаимодействие, так как оно поддерживается только конечными точками WCF.

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

Элемент привязки создает двоичную, MTOM или текстовую фабрику MessageEncoderFactory. Фабрика создает двоичный, MTOM или текстовый экземпляр MessageEncoderFactory. Обычно существует только один экземпляр. Однако при использовании сеансов для каждого сеанса могут предоставляться разные кодировщики. Двоичный кодировщик использует это для координации динамических словарей (см. раздел "Инфраструктура XML").

Методы ReadMessage и WriteMessage являются основой кодировщиков. Методы обеспечивают чтение сообщения из потока или формируют массив Byte. Байтовые массивы используются, когда транспорт работает в режиме буферизации. Сообщения всегда записываются в потоки. Если транспорт должен поместить сообщение в буфер, он предоставляет поток, который выполняет буферизацию.

Остальные члены работают с дополнительным содержимым, типами носителей и MessageVersion. Транспорт вызывает эти методы кодировщика, чтобы проверить, можно ли с их помощью декодировать входящее сообщение, или чтобы определить, является ли исходящее сообщение действительным для этого кодировщика.

Каждая из трех реализаций кодировщика добавляет свойства, относящиеся к определенному кодированию, и является полностью настраиваемой. Кодировщики также предоставляют квоты средства чтения, которые имеют защищенные параметры по умолчанию. Обсуждение квот см. в разделе "Инфраструктура XML".

Возможности кодировщиков, предоставляемых системой

Кодировщики, предоставляемые системой, имеют несколько возможностей.

Объединение в пулы

В каждой реализации выполняется попытка объединения в пул, насколько это возможно. Снижение выделения памяти- это основной способ улучшения производительности управляемого кода. Для облегчения объединения в пул в реализациях используется класс SynchronizedPool. Файл C# содержит описание дополнительных оптимизаций, используемых в этом классе.

Экземпляры XmlDictionaryReader и XmlDictionaryWriter объединяются в пул и повторно инициализируются, чтобы предотвратить выделение памяти для новых экземпляров для каждого сообщения. В случае средств чтения, обратный вызов OnClose закрывает средство чтения при вызове метода Close(). Кодировщик также повторно использует некоторые объекты состояния сообщений, используемые при создании сообщений. Размер пулов настраивается с помощью свойств MaxReadPoolSize и MaxWritePoolSize для каждого из трех классов, унаследованных от класса MessageEncodingBindingElement.

Двоичное кодирование

Если при двоичном кодировании используются сеансы, получатель сообщения должен иметь возможность взаимодействия со строкой динамического словаря. Это осуществляется путем задания префикса сообщению со строками динамического словаря. Получатель отсекает строки, добавляет их в сеанс и обрабатывает сообщение. Для правильной передачи строк словаря необходимо, чтобы транспорт был помещен в буфер.

Строки добавляются в сообщение с помощью внутреннего метода AddSessionInformationToMessage. Он добавляет строки в виде UTF-8 вначале сообщения с префиксом их длины. Затем во весь заголовок словаря добавляет префикс длины данных. Обратная операция выполняется внутренним методом ExtractSessionInformationFromMessage.

Помимо обработки ключей динамического словаря, буферизированные сообщения, связанные с сеансом, принимаются уникальным способом. Вместо создания средства чтения над документом и его обработки в двоичном кодировании используется внутренний класс MessagePatterns для разбора двоичного потока. Идея заключается в том, что большинство сообщений имеют определенный набор заголовков, которые отображаются в определенном порядке при создании WCF. Система шаблонов разделяет сообщение на части на основании ожиданий. В случае успешного выполнения она инициализирует объект MessageHeaders без анализа XML. В противном случае она возвращается к стандартному методу.

Кодирование MTOM

Класс MtomMessageEncodingBindingElement имеет дополнительное свойство конфигурации MaxBufferSize. Оно задает верхнюю границу объема данных, который можно помещать в буфер во время чтения сообщения. Может возникнуть необходимость в буферизации XML Information Set (Infoset) или других частей MIME, чтобы повторно собрать все части MIME в одно сообщение.

Для правильной работы с HTTP внутренний класс кодировщика сообщений MTOM предоставляет несколько интерфейсов API для метода GetContentType (который также является внутренним) и метода WriteMessage, который является открытым и может быть переопределен. Чтобы значения в заголовках HTTP соответствовали значениям в заголовках MIME, необходимо обеспечить более широкие возможности взаимодействия.

В кодировщике сообщений MTOM используются средства чтения текста WCF и аналогичны кодировщику текста. Основное отличие заключается в том, что он оптимизирует большой объем двоичных данных или большие двоичные объекты, не преобразовывая их в кодировку Base-64 до внедрения в байты сообщения. Вместо этого эти объекты остаются извлеченными, и на них существуют ссылки как на вложения MIME.

Запись собственного кодировщика

Чтобы реализовать собственный пользовательский кодировщик сообщений, предоставьте пользовательские реализации следующих абстрактных базовых классов.

Преобразование из хранимого в памяти представления сообщения в представление, которое можно записать в поток, инкапсулировано внутри класса MessageEncoder, который используется в качестве фабрики для средств чтения XML и средств записи XML, поддерживающих определенные типы кодирования XML.

  • Ниже представлены основные методы этого класса, которые необходимо переопределить.

  • WriteMessage, который принимает объект MessageEncodingBindingElement и записывает его в объект Stream.

  • ReadMessage, который принимает объект Stream и максимальный размер заголовка и возвращает объект Message.

Код, записываемый в этих методах, выполняет преобразование между стандартным транспортным протоколом и настроенным кодированием.

Затем следует записать в код класс фабрики, создающий пользовательский кодировщик. Переопределите свойство Encoder, чтобы обеспечить возврат экземпляра пользовательского кодировщика MessageEncoder.

Затем подключите пользовательскую фабрику MessageEncoderFactory к стеку элементов привязки, используемому для настройки службы или клиента, переопределив метод CreateMessageEncoderFactory, чтобы вернуть экземпляр этой фабрики.

Существует два примера, предоставляемых WCF, иллюстрирующих этот процесс с примером кода: Пользовательский кодировщик сообщений: Пользовательский кодировщик текста и пользовательский кодировщик сообщений: кодировщик сжатия.

См. также