dica rápida: web service pra consulta de endereço

20 02 2008

Algo que eu procuro sempre aqui no trabalho é facilitar a vida do usuário. Coisinhas pequenas, como completar o endereço a partir do cep, podem poupar um bom tempo de quem faz isso dezenas de vezes no dia.

Ao código:

Achei um monte de webservices oferecendo esse serviço. Escolhi esse, em php: web service consulta de endereço. Se você nunca usou webservice no visual studio, leia esse artigo antes de continuar.

Adicione a referência ao wsdl no seu projeto, e a cláusula using na sua unit.

Código simples que recupera os dados:

CEPService _servico = new CEPService();string[] resultado = _servico.obterLogradouro(cep).Split(',');//Quando o cep não é encontrado, a resposta do servidor vem no formato

// "CEP cep NAO ENCONTRADO" ou "Cep cep não encontrado"

if (resultado[0].StartsWith("cep", StringComparison.OrdinalIgnoreCase)   throw new CepNotFoundException("Cep não foi encontrado!");

//Quando o cep é encontrado, a resposta vem no formato

// "LOGRADOURO, BAIRRO, CIDADE, ESTADO"

Console.WriteLine("Logradouro: " + resultado[0].Trim());

Console.WriteLine("Bairro: " + resultado[1].Trim());

Console.WriteLine("Cidade: " + resultado[2].Trim());

Console.WriteLine("Estado: " + resultado[3].Trim());

Código modificado pra retornar um objeto endereço e fazer um cache bem básico:
(O construtor de Endereco tem a assinatura:
public Endereco(string cep, string logradouro, string numresidencial, string bairro, string cidade, string estado))

public class EnderecoHelper {private static CEPService _servico = new CEPService();

//Armazena os endereços de cep que não foram encontrados no banco,//pra não pesquisar duas vezes

private static IList _invalidos = new List();//Número máximo de ceps inválidos que vai ser guardada

private const int MAXINVALIDOS = 15;//Último cep pesquisado. Útil caso o mesmo cep seja

//pesquisado várias vezes seguidasprivate static Endereco _ultimoEndereco = new Endereco;

private static string _cep;
public static Endereco getEndereco(string cep) {

if (cep.Equals(_ultimoEndereco.cep)){

return _ultimoEndereco;}

if (_invalidos.Contains(cep))

{

return null;}

string[] resultado = _servico.obterLogradouro(cep).Split(',');

if (!resultado[0].StartsWith("cep", StringComparison.OrdinalIgnoreCase)) {

_ultimoEndereco = new Endereco(cep, resultado[0].Trim(), "", resultado[1].Trim(), resultado[2].Trim(), resultado[3].Trim());return _ultimoEndereco;

}else

{_invalidos.Add(cep);

if (_invalidos.Count > MAXCOUNT){

_invalidos.Clear();}

return null;}

}}

Ainda tem um monte de coisas que eu quero fazer pra melhorar isso aí. Alguns itens: Aumentar o tamanho do cache de resultados pesquisados (substituir o _ultimoEndereco por uma lista), implementar a lista de ceps inválidos como uma queue, chamar o webservie assíncronamente.
Assim que eu tiver mais tempo livre aqui no trampo eu faço isso, já que não é tão prioritária.

Espero ter ajudado alguém!





dica rápida: problema com proxy no nhibernate

13 02 2008

Tive um problema com o NHibernate e suas classes proxy que me levou um bom pedaço da tarde.

Ocorre que eu tenho uma classe “Pessoa” e suas filhas “Fisica” e Juridica”. O que eu queria era listar todas as pessoas, e quando uma fosse escolhida eu tinha que fazer uma ação baseada no seu tipo. Normal.

O problema é que minha consulta retornava objetos “CProxyTypePessoa_NHibernate_ProxyINHibernateProxy_System_Runtime_SerializationISerializable2.

Essa classe herda de “Pessoa”, mas se eu tento fazer o cast pra “Fisica” ou “Juridica” – ban! Exceção.

Depois de fuçar um bucado, achei a solução pra Java:


if (obj instanceof HibernateProxy) {
obj = ((HibernateProxy)obj).getHibernateLazyInitializer().getImplementation();
}

Em .net, ficou quase igual:

if (obj is INHibernateProxy)
{
obj = (Pessoa)NHibernateProxyHelper.GetLazyInitializer(obj as INHibernateProxy).GetImplementation();
}

Bem trivial, mas eu perdi um bom tempo pra achar isso.

ps. Usei a extensão Reflector, pro Visual Studio. Um class browser bem bacana.