Reutilizando tipos entre serviços

Ao consumir um serviço SOAP, geralmente utilizamos o documento WSDL para montar todos os artefatos necessários para efetuar a comunicação com o serviço, que é executado remotamente. Esse documento traz todas as funcionalidades expostas por aquele serviço, diretivas de como essa comunição deve ser realizada, e ainda, informações que descrevem eventuais objetos complexos que fazem parte do contrato.

Em um cenário específico, podemos criar mais de um serviço que recebe ou expõe uma mesma classe. Essa classe é criada do lado do serviço, e este tipo pode ser utilizado por qualquer serviço que consiga acessá-la. Subindo estes dois serviços, ambos podem também ser referenciados em um mesmo cliente, e quando utilizamos o Visual Studio, ele faz o download do WSDL, constrói proxy e remonta todos os tipos deste lado, para que o cliente possa enviá-los e/ou recebê-los, conseguindo assim reconstruir os objetos no cliente, trabalhando de forma tipada.

Só que quando temos esse cenário, podemos nos deparar com um detalhe no cliente que pode parecer confuso em um primeiro momento. Para exemplificarmos, repare no simples código que temos abaixo. Há uma classe chamada Usuario com apenas uma propriedade. Temos dois contratos, onde cada um está implementado em um serviço diferente, e tudo o que as operações destes contratos fazem, é enviar e receber a instância da classe Usuario.

public class Usuario
{
    public string Nome { get; set; }
}

[ServiceContract]
public interface IContrato1
{
    [OperationContract]
    Usuario Metodo1(Usuario usuario);
}

public class Servico1 : IContrato1
{
    public Usuario Metodo1(Usuario usuario) { }
}

[ServiceContract]
public interface IContrato2
{
    [OperationContract]
    Usuario Metodo2(Usuario usuario);
}

public class Servico2 : IContrato2
{
    public Usuario Metodo2(Usuario usuario) { }
}

Aqui foi omitido, mas temos o código que expõe estes dois serviços através do protocolo HTTP, utilizando o binding BasicHttpBinding. Em primeiro lugar, referenciamos na aplicação cliente o Servico1. Isso faz com que o Visual Studio crie o tipo Usuario no cliente. Depois disso, decidimos referenciar o Servico2 também neste mesmo cliente, que como sabemos, também utiliza a classe Usuario. Ao fazer isso, o Visual Studio acaba recriando o tipo Usuario, mas agora para atender o segundo serviço.

Apesar de que do lado do servidor ambos serviços utilizam o mesmo tipo, ao referenciar no cliente, o Visual Studio não tem poder de identificar isso e, consequentemente, acaba sendo criado duas classes Usuario, onde cada um atende um serviço específico, e elas não podem ser compartilhadas, ou melhor, utilizar uma delas no lugar da outra. A imagem abaixo ilustra isso essa separação:

Para certificar da independência entre as classes Usuario dos servicos, podemos visualizar o código abaixo, que é uma versão resumida do que é gerado do lado do cliente para ambos os serviços referenciados. Para cada um dos deles, temos um namespace distinto, e debaixo destes, uma classe Usuario para cada. Mais adiante, podemos perceber que no interior de cada um dos métodos, eles referenciam a respectiva classe Usuario que está dentro de seu próprio namespace.

namespace Cliente.Servico1
{
    public partial class Usuario { }
    
    public interface IContrato1
    {
        Cliente.Servico1.Usuario Metodo1(Cliente.Servico1.Usuario usuario);
    }

    public partial class Contrato1Client
    {
        public Cliente.Servico1.Usuario Metodo1(Cliente.Servico1.Usuario usuario) { }
    }
}

namespace Cliente.Servico2
{
    public partial class Usuario { }
    
    public interface IContrato2
    {
        Cliente.Servico2.Usuario Metodo2(Cliente.Servico2.Usuario usuario);
    } 

    public partial class Contrato2Client
    {
        public Cliente.Servico2.Usuario Metodo2(Cliente.Servico2.Usuario usuario) { }
    }
}

O que vimos acima, é o suficiente para proibir que se use uma mesma classe Usuario para ambos os serviços. E, para que isso seja possível, temos algumas alternativas. A primeira delas seria, depois de referenciado ambos os serviços, elegermos uma das classes Usuario e levá-la para um local centralizado, talvez em um outra namespace, e depois disso, alterar os locais em que elas estão sendo referenciadas, e apontar para esta “nova” classe/local.

Uma outra opção que temos, que acredito ser até mais elegante, seria recorrer ao utilitário svcutil.exe, e gerar todos os recursos necessários para consumir um dos serviços. Depois das classes criadas, você deve criar um projeto do tipo Class Library, e colocar essas classes que foram geradas dentro dele. Com isso, você compila o projeto e gera uma DLL contendo o proxy e a classe Usuario. De posse desta DLL, você referencia na aplicação cliente que deve utilizar este serviço. Abaixo temos a linha de comando que gera as classes para o primeiro servico:

C:>svcutil http://localhost:8888

Depois da DLL referenciada, podemos agora adicionar a referência para o segundo serviço no próprio Visual Studio, que por padrão, ele é capaz, de antes de gerar os tipos que o serviço disponibiliza, analisar se esse tipo já existe referenciado na aplicação local, e caso exista, ele o reutilizará. Abaixo temos a imagem que ilustra essa configuração de reuso:

Finalmente, a última opção que temos é o compartilhamento do tipo entre o serviço e o cliente. Inclusive, isso evita a necessidade de fazer a referência para o serviço, pois todos os artefatos que você precisa para consumir o serviço (que são os contratos), já estarão disponíveis através do compartilhamento de uma DLL entre as pontas, o que obriga ambos os lados serem .NET. Qualquer uma dessas alternativas apontadas acima, tem como objetivo o compartilhamento/centralização de tipos do lado do cliente, assim como podemos visualizar na imagem abaixo:

WCF Web API – Consumo de Serviços

O WCF-REST Starter Kit fornece uma classe chamada HttpClient, que tem a finalidade de facilitar o consumo de serviços REST em aplicações escritas em .NET (ASP.NET, Console, Windows, etc.). Apesar de ser possível efetuar o consumo de serviços utilizando as classes de baixo nível (HttpWebRequest e HttpWebResponse), a classe HttpClient acaba sendo uma classe “intermediária”, ou seja, não chega a ser tão simples como um proxy de um serviço e não tão complicada como as classes do namespace System.Net.

Essa classe possibilita o consumo deste tipo de serviço sem tirar do desenvolvedor, o controle de todo o protocolo onde as requisições e respostas trafegam, fornecendo outras classes que foram construídas com o intuito de compor e facilitar essa interação. A classe HttpClient já está disponível há algum tempo, e já falei sobre ela neste artigo.

O que quero com este breve post, é alinhar a evolução da mesma, que assim como está acontecendo com o restante do WCF-REST Starter Kit, ela também está sendo trazida para dentro do .NET/WCF, que por sua vez, se tornará a API para o consumo de serviços REST na plataforma .NET. Assim como comentei no artigo anterior, basta você adicionar o WCF Web API através do Nuget, que vários assemblies serão incluídos na aplicação, e com isso, já poderá fazer uso dela.

Ao adicionar este pacote, o assembly Microsoft.Net.Http.dll é referenciado na aplicação, o que nos permitirá fazer uso de classes como HttpClient, HttpRequestMessage (HttpRequestMessage<T>), HttpResponseMessage (HttpResponseMessage<T>), ObjectContent<T>, etc. Essas classes estão debaixo do namespace System.Net.Http, e para consumir aquele mesmo serviço de prospecção que foi criado no artigo anterior, poderíamos proceder da seguinte forma:

using (HttpClient http = new HttpClient(“http://localhost:1989/prospeccoes/&#8221;))
{
    using (HttpRequestMessage request1 = new HttpRequestMessage(HttpMethod.Post, “Adicionar”))
    {
        request1.Content = new ObjectContent<Empresa>(new Empresa() { Nome = “Empresa 1” });
        request1.Content.Headers.ContentType = new MediaTypeHeaderValue(“application/xml”);

        Console.WriteLine(http.Send(request1).StatusCode);
    }

    using (HttpRequestMessage request2 = 
        new HttpRequestMessage(HttpMethod.Get, “RecuperarEmpresasEmProspeccao”))
    {
        foreach (var item in http.Send(request2).Content.ReadAs<List<Empresa>>())
            Console.WriteLine(item.Nome);
    }
}

Como podemos perceber, grande parte do que existe no WCF-REST Starter Kit começa a ser transportado para esta nova API.

WCF Web API – Overview

Que o Windows Communication Foundation (WCF) é o pilar de comunicação dentro da plataforma .NET já é sabido. Com uma estrutura flexível, permite a construção de qualquer serviço independentemente de protocolo, pois ele não mantém ou menciona qualquer característica referente a isso, e apenas com a adição de uma pequena configuração (endpoint), é possível expor aquele serviço atendendo os mais diversos clientes.

Na versão 3.0 do .NET Framework, a Microsoft lançou o WCF, dando suporte a exposição de serviços aos mais diversos tipos de protocolos, “abraçando” várias tecnologias, onde as mensagens sempre são trocadas em formato SOAP. Muitas aplicações que precisam expor ou consumir serviços, as vezes não necessitam ter toda a complexidade e overhead que o SOAP impõe. Devido a isso, a Microsoft incluiu na versão 3.5 do .NET Framework, um conjunto de funcionalidades que permitem expor serviços construídos em WCF, seguindo os princípios REST, que possui uma afinidade com o protocolo HTTP, recorrendo a toda estrutura deste protocolo para manipular os serviços.

Mais tarde, a Microsoft também criou o WCF-Rest Starter Kit, que é uma biblioteca que traz várias funcionalidades à serviços REST, e facilita o consumo de serviços REST dentro de aplicações construídas em .NET bem mais simples do que trabalhar diretamente com a classes de baixo nível, tais como HttpWebRequest e HttpWebResponse, que estão dentro do namespace System.Net.

Depois de tudo isso, a Microsoft agora trabalha em um novo projeto chamado WCF Web API. Esta biblioteca melhora, incrementa e facilita a construção e consumo de serviços REST dentro do WCF. A grande finalidade deste novo conjunto de funcionalidades, é dar controle total ao desenvolvedor na construção de serviços REST, encapsulando toda a complexidade que o WCF possui, fornecendo classes de mais alto nível para lidar com protocolo HTTP, sua infraestrutura e as funcionalidades para qual o serviço está sendo construído.

Há algum tempo eu comentei aqui, que a Microsoft está trabalhando em um projeto para incorporar dentro do .NET Framework classes para trabalhar com serialização Json. Naquela oportunidade eu já tinha introduzido o site http://wcf.codeplex.com, que é onde a Microsoft está centralizando todas as inovações que estão sendo construídas no WCF, incluindo a Web API, que é alvo deste artigo.

Seguindo a linha de alguns outros produtos, a Microsoft também disponibilizou esta API no Nuget, ou seja, os assemblies que a compõem estão disponíveis através da adição de um packege que é acessado e instalado pelo Nuget. Ao adicionar o package WebApi.All, ele faz o download dos assemblies e já os referenciam na aplicação corrente. A imagem abaixo ilustra essa etapa:

Estrutura do Serviço

Apesar de toda a flexibilidade do WCF, uma de suas maiores reclamações é a complexidade da configuração de um serviço, e que dependendo dos recursos que você quer habilitar, a configuração pode ser ainda mais difícil. Apesar de algumas alternativas que a Microsoft criou, como é o caso do utilitário chamado WCF Service Configuration Editor, ainda assim é muito complicado, principalmente em serviços mais simples, como são os casos de serviços baseados em REST.

Essa API torna a criação de serviços REST mais simples, e a configuração para que eles funcionem quase não existe. Não que ela não seja mais necessária, mas como comentei acima, há muitas classes de mais alto nível, que encapsulam e acoplam esse serviço e sua respectiva configuração no runtime/pipeline do WCF, sem a necessidade de conhecer e gerenciar ServiceHosts, InstanceContexts, Contracts, etc. Para exemplificar, vamos criar um serviço simples, que gerenciam empresas que estão sendo prospectadas:

[ServiceContract]
public class ServicoDeProspeccao
{
    [WebGet]
    public List<Empresa> RecuperarEmpresasEmProspeccao()
    {
        //implementação
    }

    [WebInvoke]
    public void Adicionar(Empresa empresa)
    {
        //implementação
    }
}

Como podemos perceber, diferentemente de serviços que construímos até então, a classe que representa o serviço não implementa uma interface de contrato. Isso se deve ao fato de serviços REST não possuem um contrato definido, sem geração de metadados e sem operações (já que serviços REST são baseados em recursos). O atributo ServiceContractAttribute ainda continua sendo necessário, já que é esse metadado que o runtime utiliza para construir e disponibilizar o serviço para os clientes.

Os atributos WebGetAttribute e WebInvokeAttribute não são novidades, já que eles foram incluídos a partir da versão 3.5 do .NET Framework. Para recapitular, a grosso modo, WebGetAttribute permite que o acesso à operação seja feita através do método GET, enquanto o atributo WebInvokeAttribute faz com que a operação seja acessível através do método POST (padrão), PUT, etc., e você configura isso através da propriedade Method. Para mais detalhes, você pode consultar este artigo.

Utilizando a estrutura tradicional do WCF, teríamos que criar um arquivo *.svc para representar o serviço, configurar o mesmo através do Web.config, definindo os endpoints, behaviors, bindings, etc. Podemos também utilizar a classe ServiceRoute para acoplar o serviço ao sistema de roteamento de URL do ASP.NET, que apesar de trazer uma nova forma de publicar o serviço, ainda exige o conhecimento em objetos característicos do WCF. Para melhorar isso também, temos um método genérico de estensão chamado MapServiceRoute, que em um dos seus overloads, apontamos o tipo do serviço e uma string representando o prefixo. Essa configuração é realizada em nível de aplicação, e como se trata de um projeto Web, o local para colocarmos isso é o evento Application_Start, acessível através do arquivo Global.asax:

protected void Application_Start()
{
    RouteTable.Routes.MapServiceRoute<ServicoDeProspeccao>(“prospeccoes”);
}

Isso já é o suficiente para publicar e acessar o serviço. Baseando nas configurações acima, para acessar a primeira operação, utilizamos o seguinte endereço: http://localhost:1989/prospeccoes/RecuperarEmpresasEmProspeccao. Apenas variando o nome da operação, é o necessário para invocar a segunda operação, chamada de Adicionar.

Internamente, o método MapServiceRoute cria toda a estrutura necessária para um serviço WCF funcionar. Isso quer dizer que ele fará a criação do ServiceHost, definindo o serviço para aquela classe que foi criada acima. Além disso, a criação do endpoint é também realizada no interior deste método, e como sabemos, uma das características de um endpoint é o binding. E para alinhar com esta nova tecnologia, temos um novo binding, chamado de HttpBinding, que é utilizado por serviços que utilizam requisições e respostas baseadas em mensagens HTTP. Falaremos mais detalhadamente destes tipos adiante, ainda neste artigo.

Um detalhe importante é com relação a serialização das informações que são encaminhadas para o serviço e aquelas que são retornadas pelo mesmo. Como sabemos, serviços REST não possuem o envelope o SOAP, mas o seu conteúdo, na maioria das vezes, deve ser serializado em formato conhecido, como é o caso do Xml ou Json. Ainda no formato antigo, a Microsoft incluiu uma opção no binding WebHttpBinding chamada automaticFormatSelectionEnabled, que quando está definida como True, ela gerará o retorno de acordo com a necessidade do cliente. Mas como o cliente demonstra a sua necessidade? Basicamente o WCF irá retornar o conteúdo serializado de acordo com o que o cliente determina no header accept do HTTP. Por padrão, quando você omite, o WCF retorna o conteúdo serializado em Xml. Para o método RecuperarEmpresasEmProspeccao, temos o seguinte resultado:

<?xml version=”1.0″ encoding=”utf-8″?>
<ArrayOfEmpresa>
  <Empresa>
    <Nome>Empresa de Teste 1</Nome>
  </Empresa>
  <Empresa>
    <Nome>Empresa de Teste 2</Nome>
  </Empresa>
</ArrayOfEmpresa>

Agora, se ao definir o header accept como sendo application/json, as empresas serão retornadas em formato Json, facilitando o consumo através de aplicações Javascript:

[{“Nome”:”Empresa de Teste 1″}, {“Nome”:”Empresa de Teste 2″}]

Injeção de Dependência

Uma das boas práticas que temos hoje ao construir qualquer classe, seja ela para servir ou não como um serviço, é desenhá-las separando as responsabilidades de cada uma delas, e tornando o acoplamento entre elas cada vez menor, para que assim possamos ter um código simples de evoluir e manter.

Como o uso de serviços é comum nos dias de hoje, é importante que também se crie serviços baseando-se nestes princípios. Para isso, precisamos de um ponto de estensibilidade que permita interceptar a criação das classes que representam o serviço, e com isso, utilizarmos algum container de injeção de dependência para abastecermos todas as necessidades do serviço que está sendo exposto, para que ele esteja pronto para atender a requisição.

Quando utilizamos o WCF puro, o ponto de estensibilidade que permite isso é através da implementação da interface IInstanceProvider. Nesta nova API, temos um ponto de estensibilidade para fornecer a instância da classe que representa o serviço, e ali acoplarmos um código customizado. Para exemplificar, vamos incrementar a classe do serviço que fizemos acima (ServicoDeProspeccao), passando agora a depender de uma classe que é a implementação concreta de algum repositório. Temos dentro da classe um membro privado chamado repositorio do tipo IRepositorio. Esse repositório é utilizando no interior dos métodos RecuperarEmpresasEmProspeccao e Adicionar, carregando ou salvando os dados da implementação do repositório concreto que será injetado.

[ServiceContract]
public class ServicoDeProspeccao
{
    [Import]
    private IRepositorio repositorio;

    [WebGet]
    public List<Empresa> RecuperarEmpresasEmProspeccao()
    {
        return this.repositorio.RecuperarEmpresas();
    }

    [WebInvoke]
    public void Adicionar(Empresa empresa)
    {
        this.repositorio.Adicionar(empresa);
    }
}

Se repararmos, o membro repositorio está decorado com o atributo ImportAttribute. Esse atributo é fornecido pelo MEF (Managed Extensibility Framework), que se baseia nestes metadados para relacionar e abastecer o membro com a instância de uma classe que implementa esta interface (IRepositorio). Como exemplo, vamos criar um repositório em memória, que armazena os dados em uma lista, e também através de um atributo (ExportAttribute), indicaremos ao MEF que essa classe é uma implementação concreta da interface IRepositorio.

[Export(typeof(IRepositorio))]
public class RepositorioEmMemoria : IRepositorio
{
    public void Adicionar(Empresa empresa)
    {
        //implementação
    }

    public List<Empresa> RecuperarEmpresas()
    {
        //implementação
    }
}

Ainda é necessário configurar o container do nosso framework de injeção de dependência, que neste caso, é o MEF. Para isso, vamos recorrer a interface IResourceFactory, que está disponível por essa nova API. Essa interface fornece apenas dois métodos autoexplicativos: GetInstance e ReleaseInstance. O que fazemos no interior do método GetInstance é instanciar a classe que representa o serviço (ServicoDeProspeccao) e recorrer ao container para resolver as dependências do mesmo. Depois disso, retornamos o objeto já configurado para o WCF poder proceder com a execução da requisição.

private class MEFResourceFactory : IResourceFactory
{
    private CompositionContainer container;

    public MEFResourceFactory()
    {
        AssemblyCatalog catalog = new AssemblyCatalog(Assembly.GetExecutingAssembly());
        this.container = new CompositionContainer(catalog);
    }

    public object GetInstance(Type serviceType, InstanceContext instanceContext, HttpRequestMessage request)
    {
        var service = Activator.CreateInstance(serviceType);
        this.container.ComposeParts(service);

        return service;
    }

    public void ReleaseInstance(InstanceContext instanceContext, object service) { }
}

Só que isso ainda não é o suficiente. Precisamos indicar ao WCF para ele recorrer à esta factory para construir o serviço. E para isso, vamos utilizar um overload do método MapServiceRoute, que além do prefixo do serviço, recebe a instância da classe HttpHostConfiguration, que representa a configuração do host do serviço, obviamente de uma forma muito mais simplificada do que aquela que é utilizada pelo WCF. Essa classe fornece um método chamado SetResourceFactory, que como o próprio nome diz, recebe ou cria a instância da classe que representa o construtor de instâncias do serviço, que no nosso caso é aquela que acabamos de criar: MEFResourceFactory. Aquela configuração que tínhamos acima no arquivo Global.asax, agora passa a figurar da seguinte forma:

protected void Application_Start(object sender, EventArgs e)
{
    var config = HttpHostConfiguration.Create().SetResourceFactory<MEFResourceFactory>();

    RouteTable.Routes.MapServiceRoute<ServicoDeProspeccao>(“prospeccoes”, config);
}

Trabalhando com mensagens HTTP

Como sabemos, a construção de serviços WCF possibilita criarmos um contrato e, consequentemente, uma classe que representará o serviço, que por sua vez, deve implementar aquele contrato que descreve as funcionalidades expostas por ele. Ao utilizar esta técnica, construimos nosso contrato utilizando tipos simples (inteiro, decimal, boleano, etc.) ou até mesmo tipos complexos, que são classes contendo as propriedades que levam de um lado ao outro lado a informação em uma forma mais “tipada”.

Apesar disso ser interessante, e ser um grande diferencial do WCF, isso acaba sendo um problema ao trabalhar com serviços REST. Isso se deve ao fato de que há a necessidade de ter o controle total do HTTP, que é possível com o WCF puro, mas mais uma vez, exige um conhecimento de baixo nível para conseguir manipular o protocolo e suas respectivas características.

Com o intuito de facilitar e trazer, novamente, o controle para o desenvolvedor, a Microsoft inclui nesta API classes que representam a mensagem de requisição (HttpRequestMessage) e de resposta (HttpResponseMessage). Cada uma dessas classes trazem várias propriedades, onde cada uma delas expõe características do protocolo HTTP, tais como: Content, Headers, Method, Uri, StatusCode, etc.

O serviço passará a utilizar essas classes em suas operações, ou seja, receberá um parâmetro do tipo HttpRequestMessage, que possui todas as informações necessárias solicitadas pelo cliente, enquanto o retorno será do tipo HttpResponseMessage, que será onde colocaremos todas as informações de resposta para o mesmo cliente, sendo essas informações o resultado em si, o código de status do HTTP, eventuais headers, etc. Para exemplificar, vamos analisar o método Ping abaixo:

[ServiceContract]
public class ServicoDeTeste
{
    [WebGet]
    public HttpResponseMessage Ping(HttpRequestMessage request)
    {
        return new HttpResponseMessage(HttpStatusCode.OK, string.Empty)
        {
            Content = new StringContent(“algum conteudo”)
        };
    }
}

O ponto importante a se notar é a criação da classe HttpResponseMessage, que em seu construtor receber o código de status do HTTP, e logo em seguida, temos a propriedade Content, que como já suspeitamos, deve receber o resultado da operação a ser enviada para o cliente. Há uma classe abstrata que define a estrutura de um conteúdo de retorno, chamada de HttpContent. Já existem algumas implementações concretas desta classe nesta API, e uma delas é a StringContent, que recebe uma string e será devolvida para o cliente no corpo da resposta HTTP.

E se necessitarmos enviar e/ou receber objetos mais complexos, que vão além de simples strings? Para atender esta situação, na mais nova versão desta API, a Microsoft criou versões genéricas das classes HttpRequestMessage e HttpResponseMessage, que definem como parâmetro qualquer objeto que pode/deve ser serializado na comunicação entre as partes. Para exemplificar, considere o código abaixo:

[ServiceContract]
public class ServicoDeTeste
{
    [WebInvoke]
    public HttpResponseMessage<Informacao> PingTipado(HttpRequestMessage<Informacao> request)
    {
        Informacao informacao = request.Content.ReadAs();

        informacao.Dado += ” ping”;
        informacao.Codigo += 10;

        return new HttpResponseMessage<Informacao>(HttpStatusCode.OK)
        {
            Content = new ObjectContent<Informacao>(informacao)
        };
    }
}

public class Informacao
{
    public string Dado { get; set; }
    public int Codigo { get; set; }
}

Reparem que passamos a receber um parâmetro do tipo HttpRequestMessage<Informacao>, que indica que o conteúdo da mensagem será representado pelo tipo Informacao, que possui duas propriedades. Já o resultado é definido como sendo do tipo HttpResponseMessage<Informacao>, que indica que o conteúdo da mensagem também será representado pelo tipo Informacao. O que fazemos no interior deste método é recorrer à propriedade Content da classe HttpRequestMessage<T>, que retorna um objeto do tipo ObjectContent<T>, ou seja, mais uma classe que herda de HttpContent, para definir o tipo que será recebido/enviado ao HTTP. Este objeto fornece um método chamado ReadAs, que retorna a instância da classe que representa o conteúdo da mensagem, e que no caso acima, é a classe Informacao.

Depois de extraí-la, incrementamos os valores e criamos a instância da classe HttpResponseMessage<T>, também definindo a classe Informacao como tipo T, mas nada impede de utilizar um tipo diferente para a resposta. Tudo o que fazemos ali é definirmos o status como sendo OK, que caracteriza o sucesso da operação, e definimos o conteúdo da resposta através da propriedade Content, que recebe a instância da classe ObjectContent<T>, que exigirá logo no construtor da mesma, a instância do objeto tipado em T.

Para testar, podemos enviar a seguinte requisição à operação PingTipado da seguinte forma:

User-Agent: Fiddler
Content-Type: application/xml
Host: localhost:1989
Content-Length: 62

<Informacao>
  <Dado>teste</Dado>
  <Codigo>10</Codigo>
</Informacao>

E o resultado será:

HTTP/1.1 200 OK
Server: ASP.NET Development Server/10.0.0.0
Date: Mon, 18 Apr 2011 11:16:35 GMT
X-AspNet-Version: 4.0.30319
Content-Length: 105
Cache-Control: private
Content-Type: application/xml; charset=utf-8
Connection: Close

<?xml version=”1.0″ encoding=”utf-8″?>
<Informacao>
  <Dado>teste ping</Dado>
  <Codigo>20</Codigo>
</Informacao>

Estou enviado e recebendo em formato Xml porque defini o header content-type como sendo application/xml, o que me devenvolverá o resultado no mesmo formato do envio. Nada impede de enviar o conteúdo em Json e definir application/json, que também me devolverá neste formato:

User-Agent: Fiddler
Content-Type: application/json
Host: localhost:1989
Content-Length: 34

{ “Dado”:”teste”, “Codigo”:123 }

HTTP/1.1 200 OK
Server: ASP.NET Development Server/10.0.0.0
Date: Mon, 18 Apr 2011 11:20:23 GMT
X-AspNet-Version: 4.0.30319
Content-Length: 34
Cache-Control: private
Content-Type: application/json; charset=utf-8
Connection: Close

{“Codigo”:133,”Dado”:”teste ping”}

Conclusão: Vimos neste longo artigo a nova proposta da Microsoft para a criação de serviços WCF utilizando os princípios REST. Tudo o que vimos aqui, acaba nos bastidores utilizando todo o poder e flexibilização que o WCF fornece desde a sua primeira versão. Esta API vem com o intuito de redefinir como criamos e configuramos serviços baseados em REST, fornecendo classes de mais alto nível, sem exigir um conhecimento de toda arquitetura do WCF para saber onde e como interagir com um protocolo, que neste caso é o HTTP.

Tratamento de Erros e Instâncias

Uma das opções que temos para interceptar os problemas (exceções) que ocorrem dentro das operações de um serviço WCF, é a possibilidade de criar um error-handler, qual acoplamos à execução utilizando um behavior de nível de serviço. A finalidade deste handler é centralizar todo o processo de tratamento de erros, incluindo o procedimento de “tradução” da exceção em faults, e eventuais tarefas de logging.

Um artigo que escrevi há algum tempo, já detalha como criar o error-handler e o behavior para acoplá-lo à execução, mas para recapitular, o principal elemento é a interface IErrorHandler, que deve ser implementada, e mais tarde, acoplada à execução através da interface IServiceBehavior, que através do método ApplyDispatchBehavior, fornece um parâmetro do tipo ServiceHostBase, que com ele chegamos até o ChannelDispatcher, que finalmente expõe uma propriedade chamada ErrorHandlers, que é uma coleção de elementos do tipo IErrorHandler.

Como podemos perceber, o fato de ser uma coleção, podemos adicionar quantas instâncias de classes que implementam a interface IErrorHandler quisermos. Isso nos permite criar um conjunto destas classes, onde cada uma delas analisam/tratam o erro que aconteceu, permitindo isolar em cada implementação um tratamento específico, e incorporando à execução somente aquelas que são necessárias para atender aquele serviço.

internal class TratadorDeErros01 : IErrorHandler { }

internal class TratadorDeErros02 : IErrorHandler { }

internal class TratadorDeErros03 : IErrorHandler { }

Um dos métodos expostos pela interface IErrorHandler é o HandleError, que recebe como parâmetro a exceção que foi disparada pelo serviço, e retorna um valor boleano indicando se aquele erro foi ou não tratado da forma esperada por aquele tratador, e dependendo do que retornamos e como está configurado nosso serviço, influenciará drasticamente no comportamento do mesmo, em outras palavras, poderá afetar a instância da classe que representa o serviço.

Partimos do princípio que o nosso serviço esteja configurado com o modelo de gerenciamento de instância como PerSession, e há uma sessão criada. Se você tem vários tratadores acoplados à execução, como por exemplo, os três que criamos acima, eles serão disparados na ordem em que eles foram adicionados à coleção, caso uma exceção não tratada seja disparada no interior da operação que o cliente solicitou. Suponha que o segundo tratador seja capaz de entender o que representa aquela exceção e sabe como lidar com ela. Isso fará com o retorno do método HandleError seja definido como True e, consequentemente, a instância da classe que representa o serviço será mantida ativa, assim como podemos perceber através da imagem abaixo:

Tendo, no mínimo, um tratador que consiga lidar com a exceção disparada, é o suficiente para manter o serviço ativo. Agora, supondo que nenhum dos três tratadores sejam capazes de entender e tratar aquela execeção (todos os métodos HandleError retornarão False), e tendo o mesmo cenário acima, ou seja, um serviço configurado como PerSession, a instância da classe que representa o serviço será abortada, o que obrigará uma nova classe ser criada para atender aquele cliente, perdendo assim eventuais informações de estado que aquela instância mantenha. A imagem abaixo ilustra o que acabamos de ver:

Esse comportamento se deve ao fato de que uma exceção não tratada, por padrão, é entendida pelo runtime de que o serviço (instância) pode ter ficado em um estado falho, o que obriga ao WCF eliminar essa classe, a menos que você altere esse comportamento recorrendo ao recurso que vimos neste artigo.

Para finalizar, tudo o que vimos aqui serve apenas para quando utilizamos o modelo de gerenciamento de instância como PerSession. Para PerCall é indiferente, já que a instância da classe que representa o serviço serve apenas para atender a requisição corrente, e logo em seguida, é descartada. No modelo Single, tudo o que vimos aqui também não importa, já que temos uma única instância atendendo à todos os clientes, e qualquer erro não tratado não é suficiente para descartar a instância do serviço.

OT: Uso do Twitter

Como vocês já devem ter notado, eu utilizo o Twitter exclusivamente para divulgar meus artigos, e atender a demanda de pessoas que não utilizam mais RSS. Hoje, enquanto estava tweetando sobre o artigo que escrevi, descobri uma opção que listam todos os tweets que mencionam meu nickname, e olha que encontrei até minha namorada falando sobre mim! 😛

O que quero fazer com este post é pedir desculpas, pois percebi que há várias pessoas fazendo perguntas, mas como eu não sei quero utilizar ele, esses tweets que mencionam o meu nome, não são atendidos por mim. Por favor, se tiver alguma dúvida, crítica ou sugestão, por favor, utilize o formulário de contato ou a seção de comentários de cada post, que assim que possível, responderei. Desculpe-me pelo transtorno.

Controlando a exposição no WSDL

Podem haver algumas situações onde você precisa tratar individualmente cada endpoint de seu serviço WCF. Como sabemos, cada endpoint tem três características básicas, conhecidas como Address, Binding e Contract. E pela estrutura do WCF, cada endpoint define toda a infraestrutura de acesso (binding) à um determinado serviço, expondo um conjunto de operações que podem ser utilizadas (contrato).

Muitas vezes temos contratos que são construídos para atender um “público” específico. Os contratos são desenhados afim de expor uma determinada funcionalidade, e um endpoint torna isso público para aqueles que estejam interessados em consumí-lo. Por exemplo, você possui um serviço expondo um contrato, mas agora você cria um novo contrato para ficar mais coerente com a necessidade atual, mas você não pode simplesmente remover o contrato (endpoint) antigo, pois há clientes consumindo o serviço através dele, mas o que você precisa fazer, é previnir que o endpoint que expõe o contrato antigo não esteja mais visível para os novos consumidores, pois estes já devem partir para o novo contrato.

Desde a primeira versão do WCF, há um behavior em nível de contrato chamado ServiceMetadataContractBehavior, que expõe uma propriedade boleana chamada MetadataGenerationDisabled, que quando definida como True e aplicado à um contrato específico, faz com que ele não seja colocado no documento WSDL, ocultando o ponto de acesso ao serviço qual aquele contrato está sendo exposto.

Mas infelizmente essa classe era internal, ou seja, não podíamos utilizá-la na configuração dos nossos serviços, o que obrigava a fazer um certo malabarismo caso tivéssemos que ocultar o endpoint que estava expondo aquele contrato. Com o intuito de facilitar isso, a Microsoft tornou essa classe pública na versão 4.0 do WCF.

Como ela é um behavior de contrato, temos que adicioná-la no local correto, e para isso recorremos à propriedade Contract, exposta através da classe ServiceEndpoint, que nos é retornada quando chamamos o método AddServiceEndpoint, já com todas as configurações informadas nos parâmetros do mesmo. A propriedade Contract é do tipo ContractDescription, que possui uma coleção chamada Behaviors, que aceita classes que implementam a interface IContractBehavior (para informações de estensibilidade, consulte este artigo). Abaixo estamos aplicando a instância da classe ServiceMetadataContractBehavior ao endpoint que expõe a funcionalidade em seu formato antigo, e logo em seguida, adicionamos um novo endpoint que estará visível aos novos clientes.

//Endpoint Antigo
host.AddServiceEndpoint
    (
        typeof(IContrato1), 
        new BasicHttpBinding(),
        “srv”
    ).Contract.Behaviors.Add(new ServiceMetadataContractBehavior() { MetadataGenerationDisabled = true });

//Endpoint Novo
host.AddServiceEndpoint(typeof(IContrato2), new BasicHttpBinding(), “srv1”);

É importante salientar que a aplicação deste behavior não faz com que requisições que chegam para aquele endpoint sejam rejeitadas. A ideia aqui é apenas evitar que ele seja exposto no documento WSDL, e faça com que os clientes antigos ainda continuem utilizando ele como forma de acessar o serviço.

O atributo InheritedExport do MEF

A Microsoft incorporou no .NET Framework 4.0 o MEF (Managed Extensibility Framework), qual podemos utilizar para criar extensões em nossas aplicações e/ou utilizá-lo como um container de injeção de dependências. E ainda quando estava em suas primeiras versões, eu escrevi um artigo sobre ele, abordando os princípios básicos de sua utilização.

Basicamente o MEF trabalha com atributos, que decorados nos tipos envolvidos, importam ou exportam partes que são utilizadas pelo container para construir e, consequentemente, atribuir às classes que utilizam tais instâncias. Para exemplificar, veja o exemplo abaixo, onde temos uma interface que define a estrutura para logs de instruções em algum arquivo no disco:

public interface ILogger
{
    string Path { get; set; }

    void Write(string message);
}

E depois disso, temos as classes que implementam essa interface, criando os tipos concretos de acordo com a nossa necessidade. Abaixo temos essas implementações, e em cada classe que implementa a interface IFileLogger, explicitamente temos que decorá-las com o atributo ExportAttribute, para informar ao container que aquela classe é uma implementação de uma determinada interface.

[Export(typeof(IFileLogger))]
public class CsvLogger : IFileLogger { }

[Export(typeof(IFileLogger))]
public class XmlLogger : IFileLogger { }

Só que se tivermos várias implementações, estamos obrigados a especificar classe a classe esse atributo para que o runtime possa utilizá-las. A finalidade deste artigo é apenas para apresentar um atributo que também faz parte do MEF, chamado de InheritedExportAttribute, que pode ser aplicado diretamente na definição (interface), que diz ao container que todos aqueles que o implementarem, são candidatos a serem utilizados pela aplicação, e com isso, não há mais a necessidade de especificar classe a classe o atributo ExportAttribute.

[InheritedExport]
public interface ILogger
{
    string Path { get; set; }

    void Write(string message);
}

Utilizar este atributo faz com que todas as implementações sejam adicionadas ao container. Se você quiser trabalhar da forma inversa, ou seja, optar por marcar somente aquelas que não devem ser adicionadas, então você pode utilizar o atributo PartNotDiscoverableAttribute, que previne que a implementação não seja incluída no catalogo, e consequentemente, não utilizada pelo container. Exemplo:

[PartNotDiscoverable]
public class FakeLogger : IFileLogger { }

Detalhes do uso de IQueryable

Como sabemos, a Microsoft incluiu nas linguagens .NET a capacidade de se escrever queries para interrogar coleções, de forma bem semelhante ao que fazemos quando desejamos trabalhar com alguma base de dados. Esse recurso ganhou o nome de LINQ, e várias funcionalidades e mudanças essas linguagens sofreram para conseguir acomodá-lo.

Para manipular um conjunto de informações, temos que ser capazes de executar duas tarefas: escrever/executar a query e iterar pelo resultado, caso ele exista. Parte disso já é suportado pelo .NET, através da interface IEnumerable<T>, que fornece um enumerador (representado pela interface IEnumerator<T>) para iterar por alguma coleção. A parte faltante (escrita) foi implementada também como uma interface e adicionada ao .NET Framework. Para isso, passamos a ter a interface IQueryable e IQueryable<T>. Com esses interfaces, somos capazes de expressar uma query através de uma AST (Abstract Syntax Tree), e mais tarde, traduzí-la para alguma fonte de dados específica.

Hoje temos os providers: LINQ To SQL, LINQ To XML e LINQ To Entities (Entity Framework). Cada um desses providers traduzem a query para uma fonte de dados específica, tais como: SQL Server (T-SQL), XML (XPath), ou até mesmo, Oracle (PL-SQL). A interface IQueryable<T> herda diretamente de IEnumerable<T>, para assim agregar a funcionalidade de iteração do resultado. A principal propriedade que ela expõe é a Expression, que retorna a instância da classe Expression, utilizada como raiz da expression tree. A imagem abaixo ilustra a hierarquia entre elas:

Existem duas classes dentro do assembly System.Core.dll, debaixo do namespace System.Linq, e que se chamam: Enumerable e Queryable. São duas classes estáticas que, via extension methods, agregam funcionalidades aos tipos IEnumerable<T> e IQueryable<T>, respectivamente. Grande parte dessas funcionalidades (métodos), refletem operadores para manipulação da query, tais como: Where, Sum, Max, Min, etc. A principal diferença entre essas duas classes é que enquanto a classe Enumerable recebe delegates como parâmetro, a classe Queryable recebe a instância da classe Expression (que envolve um delegate), que será utilizada para montar a query, e mais tarde, ser traduzida e executada pelo provider. Abaixo temos a assinatura do método Where para as duas classes:

namespace System.Data.Linq
{
    public static class Enumerable
    {
        public static IEnumerable<TSource> Where<TSource>(
            this IEnumerable<TSource> source, Func<TSource, bool> predicate)
        {
            //…
        }
    }

    public static class Queryable
    {
        public static IQueryable<TSource> Where<TSource>(
            this IQueryable<TSource> source, Expression<Func<TSource, bool>> predicate)
        {
            //…
        }
    }
}

Ambas interfaces postergam a execução da query até o momento que você precisa realmente iterar pelo resultado. Da mesma forma, como IQueryable<T> herda de IEnumerable<T>, você pode definí-la como retorno de uma função, e mais tarde, iterar pelo resultado. Só que utilizar uma ou outra, tem um comportamento bastante diferente, que pode prejudicar a performance. Para exemplificar, vamos considerar um método que retorna as categorias da base de dados, e depois disso, vamos aplicar um filtro para retornar somente aquelas categorias cujo Id seja maior que 2. Com isso, escrevemos o seguinte código:

class Program
{
    private static DBTestesEntities ctx = new DBTestesEntities();

    static void Main(string[] args)
    {
        var query = RecuperarCategorias().Where(c => c.Id > 2);

        foreach (var item in query)
            Console.WriteLine(item.Descricao);
    }

    static IEnumerable<Dados> RecuperarCategorias()
    {
        return from c in ctx.Categorias select c;
    }
}

Repare que depois de executar o método RecurarCategorias, invocamos o método de estensão Where, e neste caso, fornecido pela classe Enumerable, já que o retorno da função é do tipo IEnumerable<T>. Ao compilar a aplicação, o compilador faz o parse da query LINQ e a transforma em dados, fazendo com que a query seja representada por objetos do tipo Expression. Abaixo temos o código decompilado, e podemos perceber que a expressão lambda que passamos para o método Where, está sendo utilizada para filtrar o resultado.

internal class Program
{
    private static DBTestesEntities ctx = new DBTestesEntities();

    private static void Main(string[] args)
    {
        IEnumerable<Categoria> query = RecuperarCategorias().Where<Categoria>(delegate (Categoria c) {
            return c.Id > 2;
        });

        foreach (Categoria item in query)
            Console.WriteLine(item.Descricao);
    }

    private static IEnumerable<Categoria> RecuperarCategorias()
    {
        ParameterExpression CS$0$0001;
        return ctx.Categorias.Select<Categoria, Categoria>(
            Expression.Lambda<Func<Categoria, Categoria>>(CS$0$0001 = Expression.Parameter(typeof(Categoria), “c”), 
            new ParameterExpression[] { CS$0$0001 }));
    }
}

O grande detalhe aqui é que as estensões para a interface IEnumerable<T>, recebem delegates como parâmetro, o que quer dizer que o filtro será aplicado do lado cliente, ou seja, ao invocar o método RecuperarCategorias, todas elas (categorias) serão retornadas, carregadas em memória, e depois aplicado o filtro, “descartando” aqueles elementos que não se enquadram no critério. Abaixo temos a query que chegou até o SQL Server:

SELECT
    [Extent1].[Id] AS [Id], 
    [Extent1].[Descricao] AS [Descricao]
FROM [dbo].[Categorias] AS [Extent1]

Agora, se o retorno da função RecuperarCategorias for do tipo IQueryable<Categoria>, o comportamento é totalmente diferente. O simples fato de alterar o tipo de retorno, é o suficiente para a compilação ser substancialmente diferente. No código abaixo temos esse código para ilustrar. Note que depois de invocar o método RecuperarCategorias, já temos o método Where na sequência. A diferença é que o método Where aqui é oriundo da classe Queryable, que ao invés de receber um delegate, recebe uma Expression, obrigando o compilador a reescrever o nosso código, transformando o filtro “c => c.Id > 2” em uma instância da classe Expression, expressando aquele mesmo critério.

internal class Program
{
    private static DBTestesEntities ctx = new DBTestesEntities();

    private static void Main(string[] args)
    {
        ParameterExpression CS$0$0000;
        IQueryable<Categoria> query = RecuperarCategorias().Where<Categoria>(
            Expression.Lambda<Func<Categoria, bool>>(
                Expression.GreaterThan(Expression.Property(CS$0$0000 = Expression.Parameter(typeof(Categoria), “c”), 
                (MethodInfo) methodof(Categoria.get_Id)), Expression.Constant(2, typeof(int))), 
            new ParameterExpression[] { CS$0$0000 }));

        foreach (Categoria item in query)
            Console.WriteLine(item.Descricao);
    }

    private static IQueryable<Categoria> RecuperarCategorias()
    {
        ParameterExpression CS$0$0001;
        return ctx.Categorias.Select<Categoria, Categoria>(
            Expression.Lambda<Func<Categoria, Categoria>>(CS$0$0001 = Expression.Parameter(typeof(Categoria), “c”), 
            new ParameterExpression[] { CS$0$0001 }));
    }
}

Apesar da ligeira mudança em tempo de compilação, isso permite o processamento remoto da query. Utilizar IQueryable<T> neste cenário, irá possibilitar o build-up de queries, ou seja, a medida que você vai adicionando critérios, operadores, etc., ele irá compondo a query principal e, finalmente, quando precisar iterar pelo resultado, apenas uma única query será disparada no respectivo banco de dados, já fazendo todo o filtro por lá, retornando menos dados. Isso pode ser comprovado visualizando a query que foi encaminhada para o banco de dados depois da alteração acima:

SELECT
    [Extent1].[Id] AS [Id], 
    [Extent1].[Descricao] AS [Descricao]
FROM [dbo].[Categorias] AS [Extent1]
WHERE [Extent1].[Id] > 2

Reportando o Progresso de Tarefas Assíncronas

Uma das necessidades que circundam o processamento assíncrono de alguma tarefa é como reportar o progresso da mesma, para dar um feedback, na maioria das vezes para um usuário, do estágio em que ela se encontra. Na maioria das vezes, isso está associado com interfaces gráficas (GUI), que por sua vez, podem trabalhar utilizando o modelo síncrono ou assíncrono.

Optamos pelo modelo assíncrono justamente permitir que o usuário possa realizar outras tarefas, enquanto aquela que é custosa seja processada por uma segunda thread. É neste ponto que temos a necessidade de saber como anda o progresso do processamento, repassando ao usuário onde se encontra a execução da tarefa.

A Microsoft trabalha em um projeto para tornar a programação assíncrona tão simples quanto a programação síncrona. Este projeto introduz duas keywords, chamadas async e await, que fazem todo o trabalho para “recriar” o código que escrevemos, montando-o da forma necessária para executá-lo de forma assíncrona, sem a necessidade de precisarmos saber como isso é realizado.

Para reportar o progresso temos dois tipos que foram introduzidos: a interface IProgress<T> e a classe EventProgress<T>. A interface genérica IProgress<T> define a estrutura de reporte de progresso, e que não fornece nada mais do que um método chamado Report, que recebe um parâmetro do tipo T, que pode ser qualquer tipo, desde um simples inteiro até uma classe que reporte informações mais detalhes do progresso da tarefa. Já a classe EventProgress<T> é uma implementação desta interface que acabamos de ver, fornecendo a opção de sermos notificados através de um evento. A imagem abaixo mostra a estrutura desses tipos:

A instância da classe EventProgress<T> pode ser criada de duas formas: através da instância diretamente ou através do método estático From. Mas a segunda opção, na versão atual (ainda em CTP), está com um problema, disparando uma exceção de forma indevida. Para exemplificar, temos um formulário Windows Forms, que ao clicar em um botão do mesmo, executaremos uma tarefa custosa, e que deverá reportar ao usuário o progresso da mesmo, utilizando esses tipos que vimos agora, em conjunto com as keywords async/await.

O primeiro passo é instanciar a classe EventProgress<T>, onde o tipo genérico T, será definido como um número inteiro, indicando a porcentagem do progresso, que utilizaremos para incrementar um controle ProgressBar. Depois da classe instanciada, vamos nos vincular ao evento ProgressChanged, que será disparado todo o momento em que o processo custoso desejar reportar o andamento do progresso do mesmo, e como já era de se esperar, um número inteiro será passado como parâmetro através da instância da classe EventArgs<T>, que possui um parâmetro genérico do mesmo tipo em que foi informado na construção da classe EventProgress<T>, acessível através da propriedade Value. O código abaixo ilustra essa parte inicial:

private EventProgress<int> report = new EventProgress<int>();

public Form1()
{
    report.ProgressChanged += (sender, args) => this.progressBar1.Value = args.Value;
}

Com a classe que servirá como forma de reportar o progresso, vamos agora criar o código que simula uma operação custosa, e invocá-lo a partir do evento Click de um botão qualquer. Note que o método ExecutarTarefaCustosa já está decorado com a keyword async. Além disso, temos a keyword await definida no interior do mesmo método, que determina que aquilo que vem na frente dela, é considerado como o callback.

private void button1_Click(object sender, EventArgs e)
{
    ExecutarTarefaCustosa();
}

private async void ExecutarTarefaCustosa()
{
    for (int i = 1; i <= 10; i++)
    {
        await TaskEx.Delay(TimeSpan.FromSeconds(2)); //Simula Processamento Custoso

        ((IProgress<int>)report).Report(i * 10);
    }
}

A cada etapa concluída (iteração), reportamos o progresso através da instância da classe EventProgress<T>. O único detalhe interessante, é que a interface IProgress<T> foi implementada de forma explícita, o que nos obriga a fazermos o casting para conseguir acessar o método Report, informando o parâmetro que representa o status do progresso.

Só que quando trabalhamos com tecnologias como Windows Forms ou WPF, há uma certa dificuldade em fazer a “conversação” entre as threads envolvidas. Por padrão, essas tecnologias utilizam apenas uma única thread, que é criada durante o início do processo. Com isso, todos os controles são criados e gerenciados por essa thread específica. Quando delegamos o processamento assíncrono para uma segunda thread, ela não poderá acessar os controles, pois os mesmos tem afinidade com a thread de criação.

Sabendo desta limitação, a classe EventProgress<T> faz uso de um SynchronizationContext internamente. Essa classe tem como finalidade fornecer uma forma de enfileirar trabalhos a serem realizados em um contexto (thread) específico. Ao criar a instância da classe SynchronizationContext, ela estabelece um vínculo com a thread onde ela está sendo criada, e ao acessá-la dentro de uma segunda thread, ele encaminhará o trabalho para ser realizado na thread ao qual está vinculada.

Finalmente, ao instanciar a classe EventProgress<T>, ela captura o SynchronizationContext corrente. Com isso, quando invocamos o método Report, ele irá disparar o método que vinculamos ao evento ProgressChanged, através do método Post da classe SynchronizationContext, que despacha (também de forma assíncrona) a execução para a thread que criou os controles, que seguramente poderá acessá-los.

Diagnósticos em Serviços WCF

O WCF fornece várias opções para monitoramento e diagnósticos de serviços. Todas estas opções não são exclusividades do mesmo, e podemos recorrer à outras ferramentas, como o próprio sistema operacional, para efetuar auxiliar na visualização e/ou entendimento de um eventual problema que possa estar ocorrendo.

Compilei essas opções em um artigo para a revista .Net Magazine, da DevMedia, afim de tentar centralizar tais opções e como fazer uso delas. Para finalizar, gostaria de agradecer ao Leandro Daniel pela oportunidade concedida.