Veja o primeiro artigo de Paulo Quicoli no site da MSDN Magazine, sobre Custom Attributes. Acesso exclusivo para Assinantes.
Artigos .NET Custom Attributes
Entendendo e Utilizando
Muito programadores que hoje iniciam seus estudos sobre o .Net se deparam com muitos conceitos e recursos que às vezes fogem de seu conhecimento, e talvez por falta de tempo ou cobrança de prazo não conseguem se aprofundar no uso de um determinado recurso que o framework oferece.
No artigo de hoje, meu primeiro pra MSDN Magazine, que apresentar um recurso magnífico, o Custom Attributes.
O que são Attributes
Todos sabemos que os arquivos PE (Portable Executable) do .NET são compostos por código IL e por Metadados. Veja na Figura 1 uma visualização da formação de um arquivo .NET PE.
Figura 1. Estrutura de um arquivo .NET PE
Os metadados provêm informações a respeito do arquivo para que o compilador JIT do .NET saiba como proceder.
Através do uso de Attributes podemos adicionar mais metadados, sejam para diretivas de compilação, informações para uso próprio da aplicação, etc. Esses metadados ficam disponíveis para qualquer aplicação que leia metadados do .NET.
Resumindo, um atributo é um objeto que representa algum dado que você precisa associar com algum elemento do seu programa. Complicou ? Vamos ver um exemplo. Quando se está desenvolvendo um web service, como que você informa que um determinado método estará disponível? Através de um attribute, veja Listagem 1.
Listagem 1. Atributo WebMethod
[WebMethod(Description="Este é um atributo")]
public Boolean ValidaCPF(string s);
Por trás do attribute WebMethod existe uma classe interna do .NET que usará as informações passadas.
Criando um Custom Attribute
O .NET nos deixa livres para criar qualquer atributo personalizado que precisemos. Aqui, vamos criar um para ser utilizado em uma implementação do padrão Strategy. Nosso strategy irá instanciar tipos de exportação de dados;
Declarando um atributo
Os atributos são declarados em classes que devemos derivar de System.Attribute. Além de derivá-las devemos informar ao compilador pra que tipo de elementos o atributo será aplicado. Veja Listagem 2.
Listagem 2. Definição de um atributo
public class StrategyAttribute : Attribute
private TipoExportacao _tipoexportacao;
public StrategyAttribute(TipoExportacao tipoExportacao)
this._tipoexportacao = tipoExportacao;
public TipoExportacao TipoDeExportacao
get{return _tipoexportacao;}
O atributo [AttributeUsage] indica os elementos onde nosso custom attribute será aplicado, em nosso caso apenas será utilizado para classes. Contudo existe uma lista de opções:
· All – qualquer elemento
· Assembly – aplicado ao próprio assembly
· Class - instancias de classes
· ClassMembers – aplicado para classes, structs, enums, construtores, métodos, propriedades, campos, eventos, delegates e interfaces
· Constructor – apenas para construtores
· Delegate – apenas a delegates
· Enum – apenas para Enums
· Event – apenas para eventos
· Field – apenas para campos
· Interface – apenas para interfaces
· Method – apenas para métodos
· Module – para um único módulo
· Parameter – aplicado a um parâmetro de um método
· Property – aplicado a um propriedade, incluindo seu Get e Set se implementado
· ReturnValue – aplicado ao retorno de algum método
· Struct – Aplicado a um struct
É uma convenção adicionar a palavra Attribute ao final do nome que queremos, observe, utilizamos StrategyAttribute , dessa forma o compilador irá permitir que chamemos nosso atributo por sua abreviação, que será seu nome sem a palavra "Attribute", ou seja, "Strategy".
Utilizando o Custom Attribute
Nossa regra de négocio é construir um strategy para exportação de dados, então vamos criar uma classe abstrata da qual os tipos de exportação vão derivar.
Listagem 3. Classe base
public abstract class Exportacoes
public abstract void Exportar();
Nosso objetivo é exportar no formato Word, Excel e PDF. Portanto vamos agora derivar esses tipos de exportação de nossa classe Exportacoes. Veja que estaremos utilizando nosso atributo.
Listagem 4. Classes de exportação
[Strategy(TipoExportacao.Word)]
public class ExportacaoWord : Exportacoes
override public void Exportar()
System.Windows.Forms.MessageBox.Show("Exportando para Word");
[Strategy(TipoExportacao.Excel)]
public class ExportacaoExcel : Exportacoes
System.Windows.Forms.MessageBox.Show("Exportando para Excel");
[Strategy(TipoExportacao.PDF)]
public class ExportacaoPDF : Exportacoes
System.Windows.Forms.MessageBox.Show("Exportando para PDF");
Em cada classe foi adicionado seu Custom Attribute, que é armazenado nos metadados do assembly.
Lendo o Custom Attribute
Nosso strategy então vai se utilizar do nosso atributo para saber qual implementação utilizar.
Listagem 5. Strategy utilizando custom attribute
public class ExportStrategyFactory
static ExportStrategyFactory()
RegisterClass(typeof(ExportacaoWord));
RegisterClass(typeof(ExportacaoExcel));
RegisterClass(typeof(ExportacaoPDF));
if (!requestStrategyImpl.IsSubclassOf(typeof(Exportacoes)))
throw new Exception("O algoritmo de exportação deve derivar da classe Exportacoes");
public static Exportacoes Create(TipoExportacao tipoExportacao)
if (attr is StrategyAttribute)
if (((StrategyAttribute)attr).TypeOfAlgorithm.Equals(
tipoExportacao))
(Exportacoes)System.Activator.CreateInstance(impl);
throw new Exception("Não foi encontrada uma implementação para esse tipo de exportação");
Através de reflexão obtemos os atributos das classes registradas. Isto é visto através do método GetCustomAttributes, veja listagem 6. Não vou entrar no mérito de como implementar o strategy, ou se esta é a melhor forma ou não, quero apenas demonstrar como criar, utilizar e ler um custom attribute.
Listagem 6. Reflexão
Utilizando o Strategy
Na Listagem 7 temos o código que utiliza nosso strategy, vale mencionar que não utilizamos nenhum estrutura condicional para determinar qual o tipo de exportação seria executado, isso está encapsulado em nossa classe ExportStrategyFactory que pode ser reutilizada por todo o sistema.
Listagem 7. Utilizando strategy
ExportStrategyFactory.Create(TipoExportacao.Word).Exportar();
ExportStrategyFactory.Create(TipoExportacao.Excel).Exportar();
ExportStrategyFactory.Create(TipoExportacao.PDF).Exportar();
No artigo de hoje vimos o que são Custom Attributes, como implementá-los e como acessá-los. Não entrei no mérito de como se implementar um strategy, nem menos mencionei que acessamos o strategy por uma factory. Esses são padrões de projeto que podem tornar aplicações orientadas a objeto muito mais flexíveis e responder à mudanças de forma mais rápida, caso queiram artigo sobre padrões de projeto, entrem em contato.
Agora é com vocês, tenham criatividade suficiente para fazer com uso desse incrível recurso do .NET FRAMEWORK, Custom Attributes.