Utilizando Generics em Serviços


Uma das grandes desilusões ao utilizar o WCF, é não conseguir utilizar tipos de dados genéricos nos serviços. Generics são tipos de dados exclusivos do .NET Framework, e utilizá-los viola os princípios da orientação a serviços, já que podem existir linguagens que não suportam essa funcionalidade. É importante dizer que isso não é uma limitação do WCF, mas sim do WSDL, que é o documento utilizado para expor os metadados para os consumidores.

O Visual Studio .NET/compilador não vão proibí-lo de utilizá-los nos contratos. O problema será na exposição das informações (via WSDL) para o cliente e, consequentemente, o proxy gerado possuirá tipos “estranhos”. Por exemplo, se uma operação do contrato retornar ou receber um tipo genérico como Teste<int>, ao gerar o proxy, ele irá criar um tipo (classe) chamado TesteOfInt, substituindo os parâmetros genéricos do mesmo, pelo tipo especificado na operação. Isso pode piorar um pouco se o parâmetro genérico informado for uma classe, como por exemplo Teste<OutraClasse>, resultando no seguinte tipo do lado do cliente: TesteOfOutraClasseKdjwuy4p, ou seja, acrescentando uma informação randômica para evitar eventuais conflitos com outros tipos no mesmo contrato.

Felizmente você pode sobrescrever esse comportamento, definindo a propriedade Name da atributo DataContractAttribute. Nela você pode especificar o formato do nome que deseja expor no WSDL. Se notarmos no primeiro exemplo abaixo, o parâmetro {0} será substituído pelo tipo genérico especificado. Caso a classe Teste suportasse mais do que um parâmetro genérico, então você pode também especificá-los para compor o nome, assim como mostrado no segundo exemplo.

[DataContract(Name = “TesteCom{0}”)]
public class Teste<T> { }

[DataContract(Name = “TesteComTipo{0}EComChave{1}”)]
public class Teste<T, D> { }

Um outro ponto importante é com relação as coleções. Elas também são características da plataforma, e não devem ser expostas além do serviço. Ao utilizar coleções que implementam direta ou indiretamente as Interfaces IEnumerable<T>, ICollection<T> ou IList<T>, o WCF automaticamente irá convertê-las em um array do tipo especificado no parâmetro genérico (<T>), facilitando a interoperabilidade com outras plataformas.

Ainda falando em coleções, ao criar uma coleção customizada, você poderá fazer uso do atributo CollectionDataContractAttribute, permitindo customizar o nome do tipo da coleção (através da propriedade Name) a ser colocado no WSDL e, consequentemente, criado no cliente (trabalhando da mesma forma que a propriedade Name do atributo DataContractAttribute). Ao utilizar este atributo, ainda temos a garantia de que o WCF verificará a existência do método Add durante a carga do serviço, e não existindo, uma exceção do tipo InvalidDataContractException será lançada. Este método se faz necessário para remontar a coleção durante a deserialização da mensagem.

Como dito acima, as coleções são características da plataforma, e não devem propagar além dos limites do serviço. Mas em algumas situações, isso pode ser interessante. Quando você está compartilhando tipos entre o cliente e o serviço (exige .NET/WCF presente dos dois lados), você pode optar por criar o proxy respeitando e preservando essas coleções. Para que isso seja possível, basta você utilizar a opções /reference/collectionType do utilitário svcutil.exe. A primeira opção determina o Assembly (reference) onde está a coleção, enquanto a segunda opção determina qual é a coleção. É importante dizer que este recurso também está disponível quando a criação do proxy é feita pela IDE do Visual Studio .NET.

Anúncios

Deixe uma resposta

Preencha os seus dados abaixo ou clique em um ícone para log in:

Logotipo do WordPress.com

Você está comentando utilizando sua conta WordPress.com. Sair / Alterar )

Imagem do Twitter

Você está comentando utilizando sua conta Twitter. Sair / Alterar )

Foto do Facebook

Você está comentando utilizando sua conta Facebook. Sair / Alterar )

Foto do Google+

Você está comentando utilizando sua conta Google+. Sair / Alterar )

Conectando a %s