Como criar atributos permitidos duplicados


96

Estou usando um atributo personalizado herdado de uma classe de atributo. Estou usando assim:

[MyCustomAttribute("CONTROL")]
[MyCustomAttribute("ALT")]
[MyCustomAttribute("SHIFT")]
[MyCustomAttribute("D")]
public void setColor()
{

}

Mas o erro "Duplicar atributo 'MyCustomAttribute'" é mostrado.
Como posso criar um atributo permitido duplicado?

Respostas:


184

Cole um AttributeUsageatributo em sua classe de Atributo (sim, isso é demais) e defina AllowMultiplecomo true:

[AttributeUsage(AttributeTargets.Method, AllowMultiple = true)]
public sealed class MyCustomAttribute: Attribute

6
Só por curiosidade - por que uma classe "selada"?
Tomas Aschan

18
A Microsoft recomenda selar classes de atributos sempre que possível: msdn.microsoft.com/en-us/library/2ab31zeh.aspx
Anton Gogolev

3
Por que selado? Resumindo: torna a pesquisa de atributos mais rápida e não tem outro impacto.
Noel Widmer

Exceto que isso impede que qualquer outra pessoa reutilize seu código. Vale ressaltar que os atributos de validação em DataAnnotations não são lacrados, o que é extremamente útil, pois possibilita a criação de especializações dos mesmos.
Neutrino

@Neutrino seal deve ser usado sempre que você não espera ou não projeta que suas classes sejam herdadas. Além disso, quando a herança pode se tornar a fonte de bugs, por exemplo: implementações thread-safe.
Francisco Neto

20

AttributeUsageAttribute ;-p

[AttributeUsage(AttributeTargets.Method, AllowMultiple = true)]
public class MyAttribute : Attribute
{}

Observe, entretanto, que se você estiver usando ComponentModel ( TypeDescriptor), ele suporta apenas uma instância de atributo (por tipo de atributo) por membro; reflexão crua suporta qualquer número ...


13

A solução de Anton está correta, mas há outra pegadinha .

Resumindo, a menos que seu atributo customizado substitua TypeId, acessá-lo por meio de PropertyDescriptor.GetCustomAttributes()retornará apenas uma única instância de seu atributo.


Mas funciona via: var customAtt = propertyInfo.GetCustomAttributes <MyCustomAttribute> ();
oo_dev

8

Por padrão, os Attributes são limitados a serem aplicados apenas uma vez a um único campo / propriedade / etc. Você pode ver isso na definição da Attributeclasse no MSDN :

[AttributeUsageAttribute(..., AllowMultiple = false)]
public abstract class Attribute : _Attribute

Portanto, como outros observaram, todas as subclasses são limitadas da mesma maneira e, caso você precise de várias instâncias do mesmo atributo, é necessário definir explicitamente AllowMultiplecomo true:

[AttributeUsage(..., AllowMultiple = true)]
public class MyCustomAttribute : Attribute

Em atributos que permitem vários usos, você também deve substituir a TypeIdpropriedade para garantir que as propriedades PropertyDescriptor.Attributes funcionem conforme o esperado. A maneira mais fácil de fazer isso é implementar essa propriedade para retornar a própria instância do atributo:

[AttributeUsage(..., AllowMultiple = true)]
public class MyCustomAttribute : Attribute
{
    public override object TypeId
    {
        get
        {
            return this;
        }
    }
}

(Postar esta resposta não porque as outras estejam erradas, mas porque esta é uma resposta mais abrangente / canônica.)


3

Como alternativa, pense em redesenhar seu atributo para permitir uma sequência.

[MyCustomAttribute(Sequence="CONTROL,ALT,SHIFT,D")]

ou

[MyCustomAttribute("CONTROL-ALT-SHIFT-D")]

em seguida, analise os valores para configurar seu atributo.

Para obter um exemplo disso, verifique AuthorizeAttribute no código-fonte ASP.NET MVC em www.codeplex.com/aspnet .


3
É ainda possível fazer com que o MyCustomAttributeconstrutor pegue um array de strings, a string[], com ou sem o paramsmodificador. Em seguida, ele pode ser aplicado com a sintaxe [MyCustom("CONTROL", "ALT", "SHIFT", "D")](com params).
Jeppe Stig Nielsen

2

Depois de adicionar o AttributeUsage, certifique-se de adicionar esta propriedade à sua classe de atributo

public override object TypeId
{
  get
  {
    return this;
  }
}
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.