Robson Alves O que torna um sonho irrealizável é a inércia de quem sonha

2set/110

Reflection e os Atributos Customizados

 

Para começarmos a falar de Reflection é imprescindivel entender melhor o conceito da “coisa”.

A Reflexão permite que você conheça um objeto pelo seu tipo (Type) e dentro do seu tipo ter acesso a praticamente tudo o que o objeto te fornece. A Reflexão é resolvida toda em tempo de execução e daí que surgem classes ou métodos do tipo genérico. Desta forma temos a possibilidade de além de acessar, os seus métodos, acessar os encapsulamentos e até mesmo enviar novos valores para o objeto em tempo de execução.

Isto soa como sem novidade alguma, afinal fazemos isso todo o tempo, mas sempre devemos respeitar o TypeSafe do C#. Em métodos genéricos, nós estamos caminhando em um nível onde, todos são aceitos independente do seu Tipo.

Para entendermos um pouco melhor essa brevissima teoria, nada melhor do que a prática.

Lembre-se de instanciar a namespace:

using System.Reflection;
        static void Main(string[] args)
        {
            //Vamos capturar o tipo da classe Math
            Type Tipo = typeof(Math);

            //Vamos capturar os Valores de PI e E, que são variaveis const da classe Math.

            FieldInfo[] field = Tipo.GetFields();

            foreach (FieldInfo Campo in field)
            {
                Console.WriteLine(Campo.Name + "=" + Campo.GetValue(typeof(Math)).ToString());
            }

            Console.ReadKey();

        }

O Foreach resultou hein:

Imagem3

Veja que com poucos passos eu fui capaz de capturar duas informações presentes dentro da class Math, sem criar instância da mesma, tudo sendo recuperado em momento de execução (RunTime).

Legal, agora o que tudo tem a ver com os atributos?

Acessando Atributos de uma Classe via Reflection

É extremamente necessário entendermos como chegar até aqui para prosseguir. Portanto vamos utilizar a mesma solução do post passado sobre atributos

Já temos nossa classe "Decorada", vamos capturar o atributo:

[Atributos(Desc: "Descrição do Atributo")]
    class ClassModelada
    {
    }

 

Crie uma classe, com o nome que desejar e nela iniciaremos a Reflexão, como exemplo abaixo:

 public void GetAttributes()
        {
            //Instanciamos o Tipo do Objeto.
            Type Tipo = typeof(ClassModelada);

            //Vamos capturar apenas os atributos do tipo Atributos (Nome do atributo)
            Object[] Attributes = Tipo.GetCustomAttributes(typeof(Atributos), true);

            if (Attributes != null)
            {

            }
        }

O resultado como esperado é apenas o atributo decorado:

 Imagem4

Fácil, se tivessem outros 3 atributos decorados no inicio da nossa classe e todos do tipo [Atributos()], todos estariam listados.

o Método, GetCustomAttributes(), serve essencialmente para capturar os tipos de atributos de Classe. Vamos partir para os atributos de propriedades, esses se tornam mais interessante pelo fato de serem vários.

Então vamos criar um novo atributo de parâmetros, para isso siga os exemplos do post passado e em AttributeTargets defina o tipo: AttributeTargets.Property, não se esqueça do: AllowMultiple = true.

Feito tudo isso teremos a classe da seguinte forma:

 [AttributeUsage(AttributeTargets.Property, AllowMultiple = true)]
    public class PropertyAttributes : System.Attribute
    {

        #region Propertys

        private SqlDbType _db_type;

        public SqlDbType dbType
        {
            get { return _db_type; }
            set { _db_type = value; }
        }

        private String _dataField;

        public String DataField
        {
            get { return _dataField; }
            set { _dataField = value; }
        }

        private int _size;

        public int Size
        {
            get { return _size; }
            set { _size = value; }
        }

        private ParameterDirection _dataDirection;

        public ParameterDirection DataDirection
        {
            get { return _dataDirection; }
            set { _dataDirection = value; }
        }
        #endregion

        ///

        /// Informe o nome da Propriedade
        /// 

        ///
Nome da Propriedade

        public PropertyAttributes(String dataField)
        {
            this.DataField = dataField;
        }

        ///

        /// Informe o Nome da Propriedade e Seu tipo de dado SQL
        /// 

        ///
Nome da Propriedade
        ///
Tipo de Dado SQL
        public PropertyAttributes(String dataField, SqlDbType dbType)
        {
            this.DataField = dataField;
            this.dbType = dbType;
        }
    }

Repare que temos dois construtores, isso fica a cargo das necessidades do atributo.

Tendo a classe feita, vamos decorar uma classe nossa de serviço.

   [Atributos(Desc: "Descrição do Atributo")]
    public class ClassModelada
    {
        private int _codigo;
        [PropertyAttributes("COD_ID", SqlDbType.Int, Size = 8)]
        public int Codigo
        {
            get { return _codigo; }
            set { _codigo = value; }
        }

        private Boolean _IsValid;

        [PropertyAttributes("COD_BIT", SqlDbType.Bit, DataDirection = ParameterDirection.InputOutput)]
        public Boolean IsValid
        {
            get { return _IsValid; }
            set { _IsValid = value; }
        }
    }

Repare que quando o parâmetro do atributo não estiver no construtor, o mesmo aparecerá no Intelissense com o Igual a frente do nome:

 Imagem5

Então, agora devemos programar nossa classe de reflexão, para pegar também os atributos das propriedades, como segue no exemplo abaixo:

 //Vamos Capturar todas as propriedades e filtra-las dentro do Foreach.
            PropertyInfo[] PropertyAttr = Tipo.GetProperties();

            foreach (PropertyInfo Propriedade in PropertyAttr)
            {
                String NomePropriedade = Propriedade.Name;
                if (Propriedade.GetCustomAttributes(typeof(PropertyAttributes), false).Count() > 0)
                {
                }
            }

            //Ou podemos utilizar um método direto, utilizando Lambda
            var AttrProperty = Tipo.GetProperties().Where(x => x.GetCustomAttributes(typeof(PropertyAttributes), false).Count() > 0);

            foreach (var Propr in AttrProperty)
            {

            }

 

Repare que os dois métodos acima fazem o mesmo trabalho, coloquei ambos para exemplificar.

Simples? acredito que sim! Eu irei mostrar como capturar o valor das propriedades em outro post, para não extender demais, e tal por que necessitamos alterar algumas coisas neste método para recuperarmos os valores de qualquer classe e não apenas de uma, portanto no próximo artigo, vou falar um pouco sobre métodos genéricos.

Obrigado.

Posts Relacionados:

  1. Atributos Customizados
      Este assunto é pouco falado, até mesmo sua utilização se torna um pouco restrita. Tive algumas idéias para a utilização deste e portanto gerou um artigo. Mas o que são esses atributos? Atributos da Classe Estes atributos você encontra...
  2. Extesion Methods
    Esse assunto é bem legal e simples, como verão abaixo. Uma classe de extensão, permite que gere novos métodos para as váriaveis do projeto como acontece em .ToString(), .ToUpper(). Pemitindo costumizar o codigo ao seu gosto, centralizando seus métodos em...
  3. Gerando Novas Thread .Net (MultThreading)
    Pois é, mas o que é uma Thread? Segundo o Wikipedia: (Fonte) Linha de execução (em inglês: Thread), é uma forma de um processo dividir a si mesmo em duas ou mais tarefas que podem ser executadas concorrentemente. O suporte...
  4. Estrutura de Classes Instanciadas e Staticas
    Neste tópico vamos falar sobre algumas particularidades da programação orientada a objetos. Todo programa possuirá suas classes e neste ambiente existirá a super-classe e a partir dela as sub-classes. Este conceito tem como foco quando falarmos de heranças entre classes....

Posted by Robson Alves

Comentários (0) Trackbacks (0)

Sem comentários


Leave a comment

(required)

Sem trackbacks