Este artigo consiste em exemplificar a utilização de alguns dos recursos do namespace System.Reflection e da classe Attributes. Como diversos artigos relacionados já foram escritos, optei por uma abordagem prática e objetiva do assunto.
O exercício tem por objetivo a criação de um método que recebe como parâmetros um objeto do tipo DropDownList e uma Lista genérica ( List<X> ), o controle será populado com os dados contidos nessa lista. Um atributo customizado servirá para marcar as propriedades da classe X que serão associadas as propriedades DataTextField e DataValueField do controle.
AttributeEntity
A Classe AttributeEntity apresenta duas propriedades booleanas, ID e Description. A primeira quando “true” indica que a propriedade marcada preencherá a DataValueField, já a segunda corresponde à propriedade DataTextField, ambas da classe DropDownList.
Essa classe herda da “Attribute”, portanto ela poderá ser usada como tal.
[AttributeEntity(Id=false, Description=true)]
Conforme definido no “AttributeUsage”, o nosso atributo customizado tem como alvo apenas propriedades, (AttributeTargets.Property) e não poderá ser utilizado mais de uma vez em um mesmo lugar (AllowMultiple=false).
Aplicável
[AttributeEntity(Id=false, Description=true)]
public string Name
{
get { return _name; }
set { _name = value; }
}
Não Aplicável
[AttributeEntity(Id=true, Description=false)]
[AttributeEntity(Id=false, Description=true)]
public string Name
{
get { return _name; }
set { _name = value; }
}using System;
using System.Collections.Generic;
using System.Text;
namespace ARTIGO.Utility
{
[AttributeUsage(AttributeTargets.Property, AllowMultiple=false)]
public class AttributeEntity : Attribute
{
#region Attributes
private bool _id;
private bool _description;
#endregion
#region Properties
public bool Id
{
get { return _id; }
set { _id = value; }
}
public bool Description
{
get { return _description; }
set { _description = value; }
}
#endregion
}
}PopulateField<X>
Na primeira linha Type t = typeof(X); ele recupera o tipo da lista parametrizada para que a reflexão seja realizada sobre ele.
No próximo passo PropertyInfo[] list = t.GetProperties(), as propriedades da classe X serão colecionadas. O objetivo é iterar por elas a fim de descobrir a que possui um atributo do tipo AttributeEntity. Como as propriedades possuem uma coleção de atributos customizados, uma nova iteração será feita para encontrar o atributo pretendido. Quando ele for encontrado, o estado de suas propriedades deverá ser verificado e com base nesses valores serão definidos os valores das propriedades DataValueField (Id) e DataTextFied (Description) do DropDownList parametrizado.
Observação: Nesse exemplo, uma mesma propriedade poderá assumir o texto e o valor de um item do controle DropDownList.
Por fim, a lista será atribuída à propriedade DataSource do controle e ele será preenchido.
PopulateField
Esse método apenas insere um item padrão no controle cujo texto é [Selecione] e o valor 0.
using System;
using System.Collections.Generic;
using System.Text;
using System.Web.UI.WebControls;
using System.Data;
using System.Reflection;
using System.Web.UI;
namespace ARTIGO.Utility
{
public class Util
{
#region Methods
/// <summary>
/// Popula o DropDownList parametrizado com a lista genérica também parametrizada.
/// </summary>
/// <typeparam name="X">Tipo dos objetos que formam a lista genérica.</typeparam>
/// <param name="pDrop">Objeto DropDownList a ser populado.</param>
/// <param name="pSource">Lista genérica que será utilizada para preencher o controle.</param>
public static void PopulateField<X>(DropDownList pDrop, List<X> pSource)
{
try
{
Type t = typeof(X);
PropertyInfo[] list = t.GetProperties();
foreach (PropertyInfo p in list)
{
object[] attributes = p.GetCustomAttributes(typeof(AttributeEntity), false);
foreach (object attribute in attributes)
{
AttributeEntity ad = (AttributeEntity)attribute;
if (ad.Id)
{
pDrop.DataValueField = p.Name;
}
if (ad.Description)
{
pDrop.DataTextField = p.Name;
}
}
}
pDrop.DataSource = pSource;
pDrop.DataBind();
}
catch
{
// ToDo -> Implementar tratamento de erros.
}
finally
{
PopulateField(pDrop);
}
}
/// <summary>
/// Popula o DropDownList parametrizado com apenas um item, chamado [Selecione] para que a lista não seja
/// apresentada sem elementos.
/// </summary>
/// <param name="pDrop">Objeto DropDownList a ser populado.</param>
private static void PopulateField(DropDownList pDrop)
{
pDrop.Items.Insert(0, new ListItem("[Selecione]", "0"));
pDrop.SelectedIndex = 0;
}
#endregion
}
}Utilizando…
using System;
using System.Collections.Generic;
using System.Text;
using ARTIGO.Utility;
namespace ARTIGO.Entities
{
public class Aluno
{
#region Attributes
private string _matricula;
private string _nome;
private DateTime _dataNacimento;
#endregion
#region Properties
[AttributeEntity(Id=true, Description=false)]
public string Matricula
{
get { return _matricula; }
set { _matricula = value; }
}
[AttributeEntity(Id = false, Description = true)]
public string Nome
{
get { return _nome; }
set { _nome = value; }
}
public DateTime DataNacimento
{
get { return _dataNacimento; }
set { _dataNacimento = value; }
}
#endregion
#region Constructors
public Aluno(string pNome, string pMatricula, DateTime pDataNascimento)
{
this.Nome = pNome;
this.Matricula = pMatricula;
this.DataNacimento = pDataNascimento;
}
#endregion
}
}
protected void Page_Load(object sender, EventArgs e)
{
DropDownList ddl;
List<Aluno> listAluno;
ddl = new DropDownList();
listAluno = new List<Aluno>();
listAluno.Add(new Aluno("Maria", "20092506", DateTime.Now));
listAluno.Add(new Aluno("Carla", "20092507", DateTime.Now));
listAluno.Add(new Aluno("Rosana", "20092508", DateTime.Now));
Util.PopulateField<Aluno>(ddl, listAluno);
this.form1.Controls.Add(ddl);
}
Resultado do teste proposto.
Código apresentado no artigo para download.







