O WCF fornece um conjunto de classes que nos permite extrair informações a respeito de um determinado serviço. Como já sabemos, o serviço pode ou não expor as informações (binding, contrato, endereço) através de um documento, que é conhecido como WSDL. Ao extrair essas informações, podemos ter acesso aos contratos, o endereço onde o serviço está publicado e também ao respectivo binding, que define como será o canal de comunicação. Com essas informações, podemos tornar o nosso código mais dinâmico, e menos dependente de uma configuração que, muitas vezes, está em hard-code.
A primeira classe que nos ajudará nisso é a MetadataExchangeClient. Com o endereço até o documento WSDL, ela é capaz de fazer o download do mesmo através do protocolo WS-MetadataExchange. Como podemos notar no exemplo abaixo, ainda em seu construtor especificamos se o modo de requisição será através de uma requisição WS-Transfer GET ou uma requisição HTTP GET. Para capturar o resultado, utilizamos o método GetMetadata, que retorna uma instância da classe MetadataSet, contendo uma coleção de seções (representadas pela classe MetadataSection), que serão utilizadas a seguir, pela classe WsdlImporter.
A classe WsdlImporter converte as informações expostas pelo WSDL, em classes que representam os endpoints, e disponibiliza vários métodos, onde podemos extrair esses endpoints individualmente, ou retornar todos os endpoints encontrados no serviço. O método ImportAllEndpoints retorna uma coleção, onde cada elemento é representado pela classe ServiceEndpoint, que por sua vez, descreve através de várias propriedades, todas as informações que estão relacionadas à um determinado endpoint, ou seja, o famoso ABC.
MetadataExchangeClient proxy =
new MetadataExchangeClient(
new Uri("net.tcp://localhost:9292/mex"),
MetadataExchangeClientMode.MetadataExchange);
ServiceEndpointCollection endpoints = new WsdlImporter(proxy.GetMetadata()).ImportAllEndpoints();
foreach (ServiceEndpoint se in endpoints)
{
Console.WriteLine("Address: {0}", se.Address);
Console.WriteLine("Binding: {0}", se.Binding);
Console.WriteLine("Contract: {0}", se.Contract.Name);
foreach (OperationDescription od in se.Contract.Operations)
Console.WriteLine("tOperation: {0} – IsOneWay: {1}", od.Name, od.IsOneWay);
}
Todas as classes utilizadas aqui estão debaixo do namespace System.ServiceModel.Description. Além disso, é importante dizer que isso não substitui o protocolo WS-Discovery, pois conhecemos qual é o endereço até o documento WSDL.