Codificadores personalizados
Este tópico discute como criar codificadores personalizados.
No Windows Communication Foundation (WCF), você usa uma associação para especificar como transferir dados em uma rede entre pontos de extremidade. Uma ligação é composta por uma sequência de elementos de ligação. Uma associação inclui elementos de vinculação de protocolo opcionais, como segurança, um elemento de vinculação de Codificador de Mensagem necessário e um elemento de vinculação de transporte necessário. Um codificador de mensagem é representado por um elemento de vinculação de codificação de mensagem. Três codificadores de mensagem estão incluídos no WCF: binário, mecanismo de otimização de transmissão de mensagem (MTOM) e texto.
Um elemento de vinculação de codificação de mensagem serializa uma saída Message e a passa para o transporte, ou recebe a forma serializada de uma mensagem do transporte e a passa para a camada de protocolo, se presente, ou para o aplicativo, se não estiver presente.
Os codificadores de mensagens transformam Message instâncias de e para uma representação de fio. Embora os codificadores sejam descritos como situados acima da camada de transporte na pilha de canais, eles residem dentro da camada de transporte. Transportes (por exemplo, HTTP) formatam a mensagem de acordo com os requisitos do padrão de transporte. Os codificadores (por exemplo, XML de texto) apenas codificam a mensagem.
Ao conectar-se a um cliente ou servidor preexistente, você pode não ter a opção de usar uma codificação de mensagem específica. No entanto, os serviços WCF podem ser disponibilizados por meio de vários pontos de extremidade, cada um com um codificador de mensagem diferente. Quando um único codificador não cobrir todo o público do seu serviço, considere expô-lo em vários pontos de extremidade. Os aplicativos cliente podem então escolher o ponto de extremidade que é melhor para eles. O uso de vários pontos de extremidade permite combinar as vantagens de diferentes codificadores de mensagens com outros elementos de ligação.
Codificadores fornecidos pelo sistema
O WCF fornece várias associações fornecidas pelo sistema que são projetadas para cobrir os cenários de aplicativo mais comuns. Cada uma dessas ligações combina um transporte, codificador de mensagens e outras opções (segurança, por exemplo). Este tópico descreve como estender os Text
Binary
codificadores , e MTOM
mensagem incluídos no WCF ou criar seu próprio codificador personalizado. O codificador de mensagem de texto suporta uma codificação XML simples, bem como codificações SOAP. O modo de codificação XML simples do codificador de mensagem de texto é chamado de codificador POX ("Plain Old XML") para distingui-lo da codificação SOAP baseada em texto.
Para obter mais informações sobre as combinações de elementos de ligação fornecidas pelas associações fornecidas pelo sistema, consulte a seção correspondente em Escolhendo um transporte.
Como trabalhar com codificadores fornecidos pelo sistema
Uma codificação é adicionada a uma associação usando uma classe derivada de MessageEncodingBindingElement.
WCF fornece os seguintes tipos de elementos de ligação derivados da MessageEncodingBindingElement classe que podem fornecer texto, binário e codificação MTOM (Message Transmission Optimization Mechanism):
TextMessageEncodingBindingElement: O codificador mais interoperável, mas menos eficiente para mensagens XML. Um serviço Web ou cliente de serviço Web geralmente pode entender XML textual. No entanto, a transmissão de grandes blocos de dados binários como texto não é eficiente.
BinaryMessageEncodingBindingElement: Representa o elemento binding que especifica a codificação de caracteres e o controle de versão de mensagens usados para mensagens XML baseadas em binário. Esta é a mais eficiente das opções de codificação, mas a menos interoperável, porque só é suportada por pontos de extremidade WCF.
MtomMessageEncodingBindingElement: Representa o elemento de vinculação que especifica a codificação de caracteres e o controle de versão de mensagens usados para uma mensagem usando uma codificação MTOM (Message Transmission Optimization Mechanism). MTOM é uma tecnologia eficiente para transmitir dados binários em mensagens WCF. O codificador MTOM tenta equilibrar entre eficiência e interoperabilidade. A codificação MTOM transmite a maioria dos XML em formato textual, mas otimiza grandes blocos de dados binários transmitindo-os como estão, sem conversão em texto.
O elemento binding cria um binário, MTOM ou texto MessageEncoderFactory. A fábrica cria uma instância binária, MTOM ou de texto MessageEncoderFactory . Normalmente, há apenas uma única instância. No entanto, se forem usadas sessões, um codificador diferente pode ser fornecido para cada sessão. O codificador binário faz uso disso para coordenar dicionários dinâmicos (consulte Infraestrutura XML).
Os ReadMessage métodos e WriteMessage são o núcleo dos codificadores. Os métodos fornecem para ler uma mensagem de um fluxo ou de uma Byte matriz. As matrizes de bytes são usadas quando o transporte está operando no modo de buffer. As mensagens são sempre gravadas em fluxos. Se o transporte deve armazenar a mensagem em buffer, ele fornece um fluxo que faz o buffer.
O restante dos membros trabalha com conteúdo de suporte, tipos de mídia e MessageVersion. O transporte chama esses métodos de codificador para testar se a mensagem de entrada pode ser decodificada por ele ou para determinar se a mensagem de saída é válida para esse codificador.
Cada uma das três implementações do codificador adiciona propriedades que são relevantes para as codificações específicas e é totalmente configurável. Os codificadores também expõem cotas de leitor que têm padrões seguros. Consulte Infraestrutura XML para obter uma discussão sobre as cotas.
Características dos codificadores fornecidos pelo sistema
Há uma série de recursos fornecidos pelos codificadores fornecidos pelo sistema.
Agrupamento
Cada uma das implementações do codificador tenta agrupar o máximo possível. Reduzir as alocações é uma maneira fundamental de melhorar o desempenho do código gerenciado. Para realizar esse pooling, as implementações usam a SynchronizedPool
classe. O arquivo C# contém uma descrição das otimizações adicionais usadas por essa classe.
XmlDictionaryReader e XmlDictionaryWriter as instâncias são agrupadas e reinicializadas para evitar a alocação de novas instâncias para cada mensagem. Para os leitores, um retorno de OnClose
chamada recupera o leitor quando Close()
é chamado. O codificador também recicla alguns objetos de estado de mensagem usados na construção de mensagens. Os tamanhos desses pools são configuráveis pelas MaxReadPoolSize
propriedades e MaxWritePoolSize
em cada uma das três classes derivadas de MessageEncodingBindingElement.
Codificação binária
Quando a codificação binária usa sessões, a cadeia de caracteres do dicionário dinâmico deve ser comunicada ao recetor da mensagem. Isso é feito prefixando a mensagem com as cadeias de caracteres dinâmicas do dicionário. O recetor retira as cadeias de caracteres, adiciona-as à sessão e processa a mensagem. A passagem correta de cadeias de caracteres de dicionário requer que o transporte seja armazenado em buffer.
As cadeias de caracteres são acrescentadas à mensagem por um método interno AddSessionInformationToMessage
. Ele adiciona as cadeias de caracteres como UTF-8 à frente da mensagem prefixada com seu comprimento. O cabeçalho do dicionário inteiro é então prefixado com o comprimento de seus dados. A operação inversa é realizada por um método interno ExtractSessionInformationFromMessage
.
Além de processar chaves de dicionário dinâmicas, as mensagens de sessão em buffer são recebidas de uma maneira exclusiva. Em vez de criar um leitor sobre o documento e processá-lo, o codificador binário usa a classe interna MessagePatterns
para desconstruir o fluxo binário. A ideia é que a maioria das mensagens tenha um determinado conjunto de cabeçalhos que aparecem em uma determinada ordem quando gerados pelo WCF. O sistema de padrões divide a mensagem com base no que espera. Se for bem-sucedido, ele inicializa um MessageHeaders objeto sem analisar o XML. Caso contrário, recorre ao método padrão.
Codificação MTOM
A MtomMessageEncodingBindingElement classe tem uma propriedade de configuração adicional chamada MaxBufferSize. Isso coloca um limite superior na quantidade de dados que é permitido armazenar em buffer durante o processo de leitura de uma mensagem. O conjunto de informações XML (Infoset), ou outras partes MIME, pode precisar ser armazenado em buffer para remontar todas as partes MIME em uma única mensagem.
Para funcionar corretamente com HTTP, a classe interna do codificador de mensagens MTOM fornece algumas APIs internas para GetContentType
(que também é interna) e WriteMessage
, que é pública e pode ser substituída. Mais comunicação deve ocorrer para garantir que os valores nos cabeçalhos HTTP estejam de acordo com os valores nos cabeçalhos MIME.
Internamente, o codificador de mensagens MTOM usa leitores de texto do WCF e é semelhante ao codificador de texto. A principal diferença é que ele otimiza grandes blocos de binários, ou "Binary Large Objects" (BLOBs), não convertendo-os em codificação Base-64 antes de serem incorporados nos bytes de mensagem. Em vez disso, esses BLOBs são mantidos extraídos e referenciados como os anexos MIME.
Escrevendo seu próprio codificador
Para implementar seu próprio codificador de mensagem personalizado, você deve fornecer implementações personalizadas das seguintes classes base abstratas:
A conversão da representação na memória de uma mensagem para uma representação que pode ser gravada em um fluxo é encapsulada dentro da MessageEncoder classe, que serve como uma fábrica para leitores XML e gravadores XML que suportam tipos específicos de codificações XML.
Os principais métodos dessa classe que você deve substituir são:
WriteMessage que pega um MessageEncodingBindingElement objeto e o grava em um Stream objeto.
ReadMessage que usa um Stream objeto e um tamanho máximo de cabeçalho e retorna um Message objeto.
É o código que você escreve nesses métodos que lida com a conversão entre o protocolo de transporte padrão e sua codificação personalizada.
Em seguida, você precisa codificar uma classe de fábrica que cria seu codificador personalizado. Substitua o Encoder para retornar uma instância do seu personalizado MessageEncoder.
Em seguida, conecte seu personalizado MessageEncoderFactory à pilha de elementos de vinculação usada para configurar o serviço ou cliente substituindo o CreateMessageEncoderFactory método para retornar uma instância dessa fábrica.
Há dois exemplos fornecidos com o WCF que ilustram esse processo com código de exemplo: Custom Message Encoder: Custom Text Encoder e Custom Message Encoder: Compression Encoder.