Pergunta

O que são atributos no .NET, para que servem e como faço para criar meus próprios atributos?

Foi útil?

Solução

Metadados.Dados sobre seus objetos/métodos/propriedades.

Por exemplo, eu poderia declarar um atributo chamado:DisplayOrder para que eu possa controlar facilmente em que ordem as propriedades devem aparecer na interface do usuário.Eu poderia então anexá-lo a uma classe e escrever alguns componentes da GUI que extraem os atributos e ordenam os elementos da UI de maneira adequada.

public class DisplayWrapper
{
    private UnderlyingClass underlyingObject;

    public DisplayWrapper(UnderlyingClass u)
    {
        underlyingObject = u;
    }

    [DisplayOrder(1)]
    public int SomeInt
    {
        get
        {
            return underlyingObject .SomeInt;
        }
    }

    [DisplayOrder(2)]
    public DateTime SomeDate
    {
        get
        {
            return underlyingObject .SomeDate;
        }
    }
}

Garantindo assim que SomeInt seja sempre exibido antes de SomeDate ao trabalhar com meus componentes GUI personalizados.

No entanto, você os verá mais comumente usados ​​fora do ambiente de codificação direta.Por exemplo, o Windows Designer os utiliza extensivamente para saber como lidar com objetos personalizados.Usando o BrowsableAttribute assim:

[Browsable(false)]
public SomeCustomType DontShowThisInTheDesigner
{
    get{/*do something*/}
}

Diz ao designer para não listar isso nas propriedades disponíveis na janela Propriedades em tempo de design, por exemplo.

Você poderia use-os também para geração de código, operações de pré-compilação (como Post-Sharp) ou operações em tempo de execução, como Reflection.Emit.Por exemplo, você pode escrever um pouco de código para criação de perfil que envolva de forma transparente cada chamada que seu código faz e cronometra.Você pode "desativar" o tempo por meio de um atributo colocado em métodos específicos.

public void SomeProfilingMethod(MethodInfo targetMethod, object target, params object[] args)
{
    bool time = true;
    foreach (Attribute a in target.GetCustomAttributes())
    {
        if (a.GetType() is NoTimingAttribute)
        {
            time = false;
            break;
        }
    }
    if (time)
    {
        StopWatch stopWatch = new StopWatch();
        stopWatch.Start();
        targetMethod.Invoke(target, args);
        stopWatch.Stop();
        HandleTimingOutput(targetMethod, stopWatch.Duration);
    }
    else
    {
        targetMethod.Invoke(target, args);
    }
}

Declará-los é fácil, basta criar uma classe que herde de Attribute.

public class DisplayOrderAttribute : Attribute
{
    private int order;

    public DisplayOrderAttribute(int order)
    {
        this.order = order;
    }

    public int Order
    {
        get { return order; }
    }
}

E lembre-se que quando você usa o atributo você pode omitir o sufixo "atributo" que o compilador adicionará isso para você.

OBSERVAÇÃO: Os atributos não fazem nada por si mesmos - é necessário que haja algum outro código que os utilize.Às vezes, esse código foi escrito para você, mas às vezes você mesmo precisa escrevê-lo.Por exemplo, o compilador C# se preocupa com alguns e certos frameworks usam alguns (por exemplo,NUnit procura [TestFixture] em uma classe e [Test] em um método de teste ao carregar um assembly).
Portanto, ao criar seu próprio atributo personalizado, esteja ciente de que isso não afetará em nada o comportamento do seu código.Você precisará escrever a outra parte que verifica os atributos (via reflexão) e agir de acordo com eles.

Outras dicas

Muitas pessoas responderam, mas ninguém mencionou isso até agora...

Os atributos são muito usados ​​com reflexão.A reflexão já é bem lenta.

Isso é vale muito a pena marcando seus atributos personalizados como sendo sealed classes para melhorar seu desempenho em tempo de execução.

Também é uma boa ideia considerar onde seria apropriado colocar tal atributo e atribuir seu atributo (!) para indicá-lo via AttributeUsage.A lista de usos de atributos disponíveis pode surpreendê-lo:

  • Conjunto
  • Módulo
  • Aula
  • Estrutura
  • Enum
  • Construtor
  • Método
  • Propriedade
  • Campo
  • Evento
  • Interface
  • Parâmetro
  • Delegar
  • Valor de retorno
  • Parâmetro genérico
  • Todos

Também é legal que o atributo AttributeUsage faça parte da assinatura do atributo AttributeUsage.Uau para dependências circulares!

[AttributeUsageAttribute(AttributeTargets.Class, Inherited = true)]
public sealed class AttributeUsageAttribute : Attribute

Atributos são um tipo de metadados para marcar classes.Isso é frequentemente usado em WinForms, por exemplo, para ocultar controles da barra de ferramentas, mas pode ser implementado em seu próprio aplicativo para permitir que instâncias de diferentes classes se comportem de maneiras específicas.

Comece criando um atributo:

[AttributeUsage(AttributeTargets.Class, AllowMultiple=false, Inherited=true)]
public class SortOrderAttribute : Attribute
{
    public int SortOrder { get; set; }

    public SortOrderAttribute(int sortOrder)
    {
        this.SortOrder = sortOrder;
    }
}

Todas as classes de atributos devem ter o sufixo "Atributo" para serem válidas.
Feito isso, crie uma classe que utilize o atributo.

[SortOrder(23)]
public class MyClass
{
    public MyClass()
    {
    }
}

Agora você pode verificar uma classe específica' SortOrderAttribute (se houver) fazendo o seguinte:

public class MyInvestigatorClass
{
    public void InvestigateTheAttribute()
    {
        // Get the type object for the class that is using
        // the attribute.
        Type type = typeof(MyClass);

        // Get all custom attributes for the type.
        object[] attributes = type.GetCustomAttributes(
            typeof(SortOrderAttribute), true);

        // Now let's make sure that we got at least one attribute.
        if (attributes != null && attributes.Length > 0)
        {
            // Get the first attribute in the list of custom attributes
            // that is of the type "SortOrderAttribute". This should only
            // be one since we said "AllowMultiple=false".
            SortOrderAttribute attribute = 
                attributes[0] as SortOrderAttribute;

            // Now we can get the sort order for the class "MyClass".
            int sortOrder = attribute.SortOrder;
        }
    }
}

Se você quiser ler mais sobre isso, você sempre pode conferir MSDN que tem uma descrição muito boa.
Espero que isso tenha ajudado você!

Um atributo é uma classe que contém algumas funcionalidades que você pode aplicar a objetos em seu código.Para criar um, crie uma classe que herda de System.Attribute.

Quanto ao que eles servem...há usos quase ilimitados para eles.

http://www.codeproject.com/KB/cs/dotnetattributes.aspx

Os atributos são como metadados aplicados a classes, métodos ou assemblies.

Eles são bons para uma série de coisas (visualização do depurador, marcação de coisas como obsoletas, marcação de coisas como serializáveis, a lista é interminável).

Criar seus próprios personalizados é muito fácil.Começa aqui:

http://msdn.microsoft.com/en-us/library/sw480ze8(VS.71).aspx

No projeto em que estou trabalhando atualmente, há um conjunto de objetos UI de vários tipos e um editor para montar esses objetos e criar páginas para uso na aplicação principal, um pouco como o designer de formulários do DevStudio.Esses objetos existem em seu próprio assembly e cada objeto é uma classe derivada de UserControl e tem um atributo personalizado.Este atributo é definido assim:

[AttributeUsage (AttributeTargets::Class)]
public ref class ControlDescriptionAttribute : Attribute
{
public:
  ControlDescriptionAttribute (String ^name, String ^description) :
    _name (name),
    _description (description)
  {
  }

  property String ^Name
  {
    String ^get () { return _name; }
  }

  property String ^Description
  {
    String ^get () { return _description; }
  }

private:
  String
    ^ _name,
    ^ _description;
};

e eu aplico isso a uma classe como esta:

[ControlDescription ("Pie Chart", "Displays a pie chart")]
public ref class PieControl sealed : UserControl
{
  // stuff
};

que é o que os pôsteres anteriores disseram.

Para usar o atributo, o editor possui um Generic::List <Type> contendo os tipos de controle.Há uma caixa de listagem da qual o usuário pode arrastar e soltar na página para criar uma instância do controle.Para preencher a caixa de listagem, recebo o ControlDescriptionAttribute para o controle e preencha uma entrada na lista:

// done for each control type
array <Object ^>
  // get all the custom attributes
  ^attributes = controltype->GetCustomAttributes (true);

Type
  // this is the one we're interested in
  ^attributetype = ECMMainPageDisplay::ControlDescriptionAttribute::typeid;

// iterate over the custom attributes
for each (Object ^attribute in attributes)
{
  if (attributetype->IsInstanceOfType (attribute))
  {
    ECMMainPageDisplay::ControlDescriptionAttribute
      ^description = safe_cast <ECMMainPageDisplay::ControlDescriptionAttribute ^> (attribute);

    // get the name and description and create an entry in the list
    ListViewItem
      ^item = gcnew ListViewItem (description->Name);

    item->Tag = controltype->Name;
    item->SubItems->Add (description->Description);

    mcontrols->Items->Add (item);
    break;
  }
}

Observação:O exposto acima é C ++/CLI, mas não é difícil converter em C# (sim, eu sei, C ++/CLI é uma abominação, mas é com isso que tenho que trabalhar :-()

Você pode colocar atributos na maioria das coisas e há toda uma gama de atributos predefinidos.O editor mencionado acima também procura atributos personalizados nas propriedades que descrevem a propriedade e como editá-la.

Depois de entender toda a ideia, você se perguntará como conseguiu viver sem eles.

Como dito, os atributos são relativamente fáceis de criar.A outra parte do trabalho é criar código que o utilize.Na maioria dos casos você usará a reflexão em tempo de execução para alterar o comportamento com base na presença de um atributo ou em suas propriedades.Existem também cenários em que você inspecionará atributos no código compilado para fazer algum tipo de análise estática.Por exemplo, os parâmetros podem ser marcados como não nulos e a ferramenta de análise pode usar isso como uma dica.

Usar os atributos e conhecer os cenários apropriados para seu uso é a maior parte do trabalho.

Atributos são, essencialmente, bits de dados que você deseja anexar ao seu tipos (classes, métodos, eventos, enums, etc.)

A idéia é que em tempo de execução algum outro tipo/estrutura/ferramenta consulte seu digite as informações no atributo e aja de acordo com elas.

Assim, por exemplo, o Visual Studio pode consultar os atributos em um controle de terceiros para descobrir quais propriedades do controle devem aparecer no painel Propriedades em tempo de design.

Os atributos também podem ser usados ​​na Programação Orientada a Aspectos para injetar/manipular objetos em tempo de execução com base nos atributos que os decoram e adicionar validação, registro, etc.aos objetos sem afetar a lógica de negócios do objeto.

Você pode usar atributos personalizados como uma maneira simples de definir valores de tags em subclasses sem precisar escrever o mesmo código repetidamente para cada subclasse.me deparei com um lindo exemplo conciso de John Waters de como definir e usar atributos personalizados em seu próprio código.

Há um tutorial em http://msdn.microsoft.com/en-us/library/aa288454(VS.71).aspx

Para começar a criar um atributo, abra um arquivo de origem C#, digite attribute e pressione [TAB].Ele será expandido para um modelo para um novo atributo.

Atributos também são comumente usados ​​para Programação Orientada a Aspectos.Para um exemplo disso, confira o PostSharp projeto.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top