Canais iMasters

.NET + Javascript + Desenvolvimento + Ruby on Rails

Usando tipos anônimos como parâmetro

Quando a Microsoft anunciou os tipos anônimos (Anonymous Types) eu fiquei bastante contente, era possível criar tipos rapidamente de uma forma muito fácil. Para quem ainda não conhece essa nova funcionalidade aqui vai o link.

Olhando a sintaxe de construção de um tipo anônimo logo associei aos arrays associativos das linguagens de script, conhecidos como Hash. O C# sempre teve o objeto Hashtable, mas não é flexível comparando com linguagens como Ruby ou Javascript. Só pra exemplificar o que estou dizendo:

No Ruby posso chamar um método passando um hash como parâmetro, sintaxe bastante utilizada no Ruby on Rails, dessa forma:

link_to("Profile", :controller => "profiles", :action => "show")
link_to("Profile", :controller => "profiles", :id => @id)

Nas duas linhas de exemplo os dois últimos itens formam uma Hashtable, no caso do Ruby se chama Hash. Do lado do método também fica fácil de capturar o que foi passado. Com tipos anônimos do C# podemos fazer uma sintaxe bem próxima, que ficaria assim:

LinkTo("Profile", new { Controller = "profiles", Action = "show" });
LinkTo("Profile", new { Controller = "profiles", Id = id });

Mas por que utilizar essa forma de passar parâmetros?

É elegante e limpo em alguns casos. Alguns métodos realizam funções onde é necessário informar MUITOS parâmetros para que se tenha um bom nível de customização da ação que será realizada. E como alguns parâmetros são opcionais acabamos tendo que criar várias sobrecargas para o mesmo método, a fim de facilitar a vida de quem vai usar.

No exemplo acima estamos utilizando um método cria um link HTML em um ambiente MVC. Como são muitos parâmetros (texto, controller, action, style, class, id, querystring) e raramente usaremos todos, utilizamos um tipo anônimo para informar os parâmetros "opcionais". Assim não precisaremos encher a nossa classe com sobrecargas do método LinkTo.

Outro ganho que temos é na hora de adicionar mais um parâmetro ao método. Adicionamos no tipo anônimo e não precisamos alterar as chamadas na aplicação inteira. Mesmo com refactoring isso às vezes é problemático.

Ok! Agora, como crio meu próprio método?

Para ver como funciona vamos implementar um método que cria links, parecido com o que exemplifiquei antes. Primeiro veremos como fica o método que vou chamar de "CriaLink", depois explico o que ele está fazendo:

public static object GetPropertyValue(this object obj, string propertyName)
{
try
{
return obj.GetType().GetProperty(propertyName).GetValue(obj, null);
}
catch
{
return null;
}
}
public string CriaLink(string titulo, object parametros)
{
var para = (string) parametros.GetPropertyValue("Para");
var descricao = (string) parametros.GetPropertyValue("Descricao");
var borda = (int?) parametros.GetPropertyValue("Borda");

var linkBuilder = new StringBuilder();

linkBuilder.Append("<a");

if(!String.IsNullOrEmpty(para))
{
linkBuilder.AppendFormat(" href='{0}'", para);
}

if(!String.IsNullOrEmpty(descricao))
{
linkBuilder.AppendFormat(" title='{0}'", descricao);
}

if(borda != null && borda > 0)
{
linkBuilder.AppendFormat(" style='border: {0}px solid silver'", borda);
}

linkBuilder.AppendFormat(">{0}</a>", titulo);

return linkBuilder.ToString();
}
CriaLink("Google", new { Para = "http://www.google.com", Descricao = "Clique aqui para acessar o Google.", Borda = 2 });
// <a href='http://www.google.com' title='Clique aqui para acessar o Google.' style='border: 2px solid silver'>Google</a>

CriaLink("Globo", new { Para = "http://www.globo.com", Borda = 2 });
// <a href='http://www.globo.com' style='border: 2px solid silver'>Globo</a>

CriaLink("Home", new { Para = "/Index.html", Descricao = "Voltar para a página inicial." });
// <a href='/Index.html' title='Voltar para a página inicial.'>Home</a>

Criei um extension method de nome GetPropertyValue na classe Object para quem não sabe do que se trata extension methods falei sobre isso aqui. Esse método busca o valor da propriedade de qualquer objeto passando apenas seu nome. Isso vai ser muito útil para tratar os tipos anônimos.

Já na implementação do método "CriaLink" primeiramente busco os valores das possíveis propriedades atribuídas ao tipo anônimo passado por parâmetro, que é do tipo Object porque não é possível prever um tipo anônimo. O método GetPropertyValue já se responsabiliza por saber se existe ou não a propriedade, no caso de ela não existir o resultado é null.

Depois fica mais simples. Apenas criei uma StringBuilder para concatenar a tag de link que vou criar. Testo se as variáveis provenientes dos parâmetros possuem valores e concateno o valor relativo a cada propriedade.

Por último, mostro como podemos utilizar o método que criamos e o resultado obtido.

Já falei aqui o quanto sou fã da flexibilidade das linguagens de script. O C# tem incorporado algumas funcionalidades dessas linguagens e, mesmo assim, ao contrário do que eu imaginava, consegue manter sua característica de ser fortemente tipado. Temos que aproveitar isso e tornar nosso código mais inteligente.

Espero que tenham gostado e qualquer duvida ou sugestão é só entrar em contato ou comentar aqui mesmo. Até mais.


Comente também

1 Comentário

Junio Silva
Junio Silva

Muito interessante, agora com o C# 4.0 creio que fica ainda mais fácil fazer tais métodos.

Qual a sua opinião?

Comentários considerados ofensivos serão moderados.

Parceiros

IBM
PagSeguro
Internet Innovation
Dialhost
HostNet
Tecla
KingHost
DotStore
Dinamize