property - field attributes c#




Atributos Mais Úteis (20)

Eu sei que atributos são extremamente úteis. Existem algumas predefinidas, como [Browsable(false)] que permite ocultar propriedades na guia de propriedades. Aqui está uma boa pergunta explicando os atributos: O que são atributos no .NET?

Quais são os atributos predefinidos (e seu namespace) que você realmente usa em seus projetos?


Apenas alguns atributos obtêm suporte ao compilador, mas um uso muito interessante de atributos está no AOP: O PostSharp usa seus atributos sob medida para injetar IL em métodos, permitindo que todos os tipos de habilidades ... log / trace sejam exemplos triviais - mas alguns outros bons exemplos são coisas como implementação automática de INotifyPropertyChanged ( here ).

Alguns que ocorrem e afetam o compilador ou o tempo de execução diretamente :

  • [Conditional("FOO")] - as chamadas para este método (incluindo a avaliação de argumentos) ocorrem apenas se o símbolo "FOO" for definido durante a compilação
  • [MethodImpl(...)] - usado para indicar algumas coisas como sincronização, inline
  • [PrincipalPermission(...)] - usado para injetar verificações de segurança no código automaticamente
  • [TypeForwardedTo(...)] - usado para mover tipos entre montagens sem recriar os chamadores

Para coisas que são verificadas manualmente via reflexão - eu sou um grande fã dos atributos System.ComponentModel ; coisas como [TypeDescriptionProvider(...)] , [TypeConverter(...)] e [Editor(...)] que podem mudar completamente o comportamento dos tipos em cenários de vinculação de dados (ou seja, propriedades dinâmicas, etc.).


Em nosso projeto atual, usamos

[ComVisible(false)]

Ele controla a acessibilidade de um tipo ou membro gerenciado individual ou de todos os tipos em um assembly para COM.

Mais informações



Eu gero classe de entidade de dados via CodeSmith e uso atributos para alguma rotina de validação. Aqui está um exemplo:

/// <summary>
/// Firm ID
/// </summary>
[ChineseDescription("送样单位编号")]
[ValidRequired()]
public string FirmGUID
{
    get { return _firmGUID; }
    set { _firmGUID = value; }
}

E eu tenho uma classe de utilitário para fazer a validação com base nos atributos anexados à classe de entidade de dados. Aqui está o código:

namespace Reform.Water.Business.Common
{
/// <summary>
/// Validation Utility
/// </summary>
public static class ValidationUtility
{
    /// <summary>
    /// Data entity validation
    /// </summary>
    /// <param name="data">Data entity object</param>
    /// <returns>return true if the object is valid, otherwise return false</returns>
    public static bool Validate(object data)
    {
        bool result = true;
        PropertyInfo[] properties = data.GetType().GetProperties();
        foreach (PropertyInfo p in properties)
        {
            //Length validatioin
            Attribute attribute = Attribute.GetCustomAttribute(p,typeof(ValidLengthAttribute), false);
            if (attribute != null)
            {
                ValidLengthAttribute validLengthAttribute = attribute as ValidLengthAttribute;
                if (validLengthAttribute != null)
                {
                    int maxLength = validLengthAttribute.MaxLength;
                    int minLength = validLengthAttribute.MinLength;
                    string stringValue = p.GetValue(data, null).ToString();
                    if (stringValue.Length < minLength || stringValue.Length > maxLength)
                    {
                        return false;
                    }
                }
            }
            //Range validation
            attribute = Attribute.GetCustomAttribute(p,typeof(ValidRangeAttribute), false);
            if (attribute != null)
            {
                ValidRangeAttribute validRangeAttribute = attribute as ValidRangeAttribute;
                if (validRangeAttribute != null)
                {
                    decimal maxValue = decimal.MaxValue;
                    decimal minValue = decimal.MinValue;
                    decimal.TryParse(validRangeAttribute.MaxValueString, out maxValue);
                    decimal.TryParse(validRangeAttribute.MinValueString, out minValue);
                    decimal decimalValue = 0;
                    decimal.TryParse(p.GetValue(data, null).ToString(), out decimalValue);
                    if (decimalValue < minValue || decimalValue > maxValue)
                    {
                        return false;
                    }
                }
            }
            //Regex validation
            attribute = Attribute.GetCustomAttribute(p,typeof(ValidRegExAttribute), false);
            if (attribute != null)
            {
                ValidRegExAttribute validRegExAttribute = attribute as ValidRegExAttribute;
                if (validRegExAttribute != null)
                {
                    string objectStringValue = p.GetValue(data, null).ToString();
                    string regExString = validRegExAttribute.RegExString;
                    Regex regEx = new Regex(regExString);
                    if (regEx.Match(objectStringValue) == null)
                    {
                        return false;
                    }
                }
            }
            //Required field validation
            attribute = Attribute.GetCustomAttribute(p,typeof(ValidRequiredAttribute), false);
            if (attribute != null)
            {
                ValidRequiredAttribute validRequiredAttribute = attribute as ValidRequiredAttribute;
                if (validRequiredAttribute != null)
                {
                    object requiredPropertyValue = p.GetValue(data, null);
                    if (requiredPropertyValue == null || string.IsNullOrEmpty(requiredPropertyValue.ToString()))
                    {
                        return false;
                    }
                }
            }
        }
        return result;
    }
}
}

Eu gosto de usar o atributo [ThreadStatic] em combinação com programação baseada em thread e pilha. Por exemplo, se eu quiser um valor que eu queira compartilhar com o resto de uma sequência de chamadas, mas eu quero fazê-lo fora da banda (isto é, fora dos parâmetros de chamada), eu poderia empregar algo assim.

class MyContextInformation : IDisposable {
    [ThreadStatic] private static MyContextInformation current;

    public static MyContextInformation Current {
        get { return current; }
    }

    private MyContextInformation previous;


    public MyContextInformation(Object myData) {
       this.myData = myData;
       previous = current;
       current = this;
    }

    public void Dispose() {
       current = previous;
    }
}

Posteriormente no meu código, eu posso usar isso para fornecer informações contextuais fora da banda para as pessoas a jusante do meu código. Exemplo:

using(new MyContextInformation(someInfoInContext)) {
   ...
}

O atributo ThreadStatic permite que eu esclareça a chamada apenas para o encadeamento em questão, evitando o problema confuso de acesso a dados em encadeamentos.


Eu sempre uso os atributos DisplayName , Description e DefaultValue sobre propriedades públicas dos meus controles de usuário, controles personalizados ou qualquer classe que eu edito através de uma grade de propriedades. Essas marcas são usadas pelo .NET PropertyGrid para formatar o nome, o painel de descrição e os valores em negrito que não estão definidos para os valores padrão.

[DisplayName("Error color")]
[Description("The color used on nodes containing errors.")]
[DefaultValue(Color.Red)]
public Color ErrorColor
{
    ...
} 

Eu só queria que o IntelliSense do Visual Studio levasse em consideração o atributo Description se nenhum comentário XML fosse encontrado. Evitaria ter que repetir a mesma sentença duas vezes.


Eu tenho usado o [DataObjectMethod] ultimamente. Ele descreve o método para que você possa usar sua classe com o ObjectDataSource (ou outros controles).

[DataObjectMethod(DataObjectMethodType.Select)] 
[DataObjectMethod(DataObjectMethodType.Delete)] 
[DataObjectMethod(DataObjectMethodType.Update)] 
[DataObjectMethod(DataObjectMethodType.Insert)] 

Mais informações


Meu voto seria para [Conditional]

[Conditional("DEBUG")]
public void DebugOnlyFunction()
{
    // your code here
}

Você pode usar isso para adicionar uma função com recursos avançados de depuração; como Debug.Write , ele é chamado apenas em compilações de depuração e, portanto, permite encapsular uma lógica de depuração complexa fora do fluxo principal de seu programa.


No espírito de Hofstadt, o [Attribute] é muito útil, pois é como você cria seus próprios atributos. Eu usei atributos em vez de interfaces para implementar sistemas de plugins, adicionar descrições a Enums, simular vários despachos e outros truques.


No topo da minha cabeça, aqui está uma lista rápida, classificada por freqüência de uso, dos atributos predefinidos que eu realmente uso em um grande projeto (~ 500k LoCs):

Sinalizadores, Serializável, WebMethod, COMVisible, TypeConverter, Condicional, ThreadStatic, Obsoleto, InternalsVisibleTo, DebuggerStepThrough.


Os atributos que mais uso são aqueles relacionados à serialização de XML.

XmlRoot

XmlElement

XmlAttribute

etc ...

Extremamente útil ao fazer qualquer análise XML ou serialização rápida e suja.



Sendo um desenvolvedor de nível intermediário que eu gosto

System.ComponentModel.EditorBrowsableAttribute Permite ocultar propriedades para que o desenvolvedor da UI não fique sobrecarregado com propriedades que não precisam ver.

System.ComponentModel.BindableAttribute Algumas coisas não precisam ser databound. Novamente, diminui o trabalho que os desenvolvedores da interface do usuário precisam fazer.

Eu também gosto do DefaultValue que Lawrence Johnston mencionou.

System.ComponentModel.BrowsableAttribute e os Flags são usados ​​regularmente.

Eu uso System.STAThreadAttribute System.ThreadStaticAttribute quando necessário.

A propósito. Eu estes são tão valiosos para todos os desenvolvedores do framework .Net.


Here está o post sobre o interessante atributo InternalsVisibleTo . Basicamente o que faz imita a funcionalidade de acesso de amigos C ++. É muito útil para testes unitários.


[Flags] é bastante útil. Açúcar sintático, com certeza, mas ainda bem legal.

[Flags] 
enum SandwichStuff
{
   Cheese = 1,
   Pickles = 2,
   Chips = 4,
   Ham = 8,
   Eggs = 16,
   PeanutButter = 32,
   Jam = 64
};

public Sandwich MakeSandwich(SandwichStuff stuff)
{
   Console.WriteLine(stuff.ToString());
   // ...
}

// ...

MakeSandwich(SandwichStuff.Cheese 
   | SandwichStuff.Ham 
   | SandwichStuff.PeanutButter);
// produces console output: "Cheese, Ham, PeanutButter"

Leppie aponta algo que eu não havia percebido e que, em vez disso, diminui meu entusiasmo por esse atributo: ele não instrui o compilador a permitir combinações de bits como valores válidos para variáveis ​​de enumeração, o compilador permite isso para enumerações de qualquer maneira. Meu fundo C ++ mostrando através de ... suspiro


System.Obsolete é um dos atributos mais úteis no framework, na minha opinião. A capacidade de gerar um aviso sobre o código que não deve mais ser usado é muito útil. Adoro ter uma maneira de dizer aos desenvolvedores que algo não deve mais ser usado, além de ter uma maneira de explicar por que e apontar para a melhor / nova maneira de fazer alguma coisa.

O Conditional attribute é bastante útil também para o uso de depuração. Ele permite que você adicione métodos em seu código para propósitos de depuração que não serão compilados quando você construir sua solução para o release.

Em seguida, há muitos atributos específicos dos Controles da Web que considero úteis, mas eles são mais específicos e não têm nenhum uso fora do desenvolvimento de controles de servidor do que encontrei.


[DeploymentItem("myFile1.txt")] Doc MSDN no DeploymentItem

Isso é realmente útil se você estiver testando em um arquivo ou usando o arquivo como entrada para seu teste.


[EditorBrowsable(EditorBrowsableState.Never)] permite ocultar propriedades e métodos do IntelliSense se o projeto não estiver em sua solução. Muito útil para ocultar fluxos inválidos para interfaces fluentes. Com que frequência você deseja GetHashCode () ou Equals ()?

Para MVC [ActionName("Name")] permite que você tenha uma ação Get e Post com a mesma assinatura de método, ou use traços no nome da ação, que de outra forma não seria possível sem criar uma rota para ela.


[System.Security.Permissions.PermissionSetAttribute] permite que ações de segurança para um PermissionSet sejam aplicadas ao código usando a segurança declarativa.

// usage:
public class FullConditionUITypeEditor : UITypeEditor
{
    // The immediate caller is required to have been granted the FullTrust permission.
    [PermissionSetAttribute(SecurityAction.LinkDemand, Name = "FullTrust")]
    public FullConditionUITypeEditor() { }
}





.net-attributes