Як створити повторювані дозволені атрибути


96

Я використовую власний атрибут, успадкований від класу атрибутів. Я використовую це так:

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

}

Але відображається помилка "Повторюваний атрибут" MyCustomAttribute "".
Як я можу створити повторюваний дозволений атрибут?

Відповіді:


184

Прикріпіть AttributeUsageатрибут до свого класу атрибутів (так, це рот) і встановіть AllowMultipleзначення true:

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

6
Просто цікаво - чому "запечатаний" клас?
Томаш Ашан

18
Microsoft рекомендує запечатувати класи атрибутів, коли це можливо: msdn.microsoft.com/en-us/library/2ab31zeh.aspx
Антон Гоголев

3
Чому запечатаний? Коротше кажучи: робить пошук атрибутів швидшим і не має іншого впливу.
Ноель Відмер,

За винятком того, що це заважає комусь більше використовувати ваш код. Варто зазначити, що атрибути перевірки в DataAnnotations не герметизовані, що надзвичайно корисно, оскільки дає можливість створювати їх спеціалізації.
Нейтрино

Запечатаний @Neutrino слід використовувати, коли ви не сподіваєтесь на те, що ваші заняття не передаються у спадок Плюс до того, коли спадкування може стати джерелом помилок, наприклад: безпечні для потоків реалізації.
Франсіско Нето

20

AttributeUsageAttribute ;-p

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

Однак зауважте, що якщо ви використовуєте ComponentModel ( TypeDescriptor), він підтримує лише один екземпляр атрибута (для кожного типу атрибута) на кожного члена; необроблене відображення підтримує будь-яке число ...


13

Рішення Антона правильне, але є ще одна ґотча .

Коротше кажучи, якщо ваш власний атрибутивний режим не замінює TypeId, то доступ до нього через нього PropertyDescriptor.GetCustomAttributes()поверне лише один екземпляр вашого атрибута.


Але це працює через: var customAtt = propertyInfo.GetCustomAttributes <MyCustomAttribute> ();
oo_dev

8

За замовчуванням Attributes обмежуються тим, що застосовуються лише один раз до одного поля / властивості / тощо. Це можна побачити з визначення Attributeкласу на MSDN :

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

Тому, як і інші відзначали, все підкласи обмежені таким же чином, і якщо вам буде потрібно кілька примірників одного і того ж атрибута, вам потрібно явно встановити AllowMultipleна true:

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

Для атрибутів, що дозволяють багаторазове використання, слід також перевизначити TypeIdвластивість, щоб забезпечити PropertyDescriptor.Attributes роботу таких властивостей, як очікувано. Найпростіший спосіб зробити це - застосувати це властивість для повернення самого екземпляра атрибута:

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

(Опублікувати цю відповідь не тому, що інші помиляються, а тому, що це більш всебічна / канонічна відповідь.)


3

Як альтернатива, подумайте про перероблення свого атрибуту, щоб дозволити послідовність.

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

або

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

потім проаналізуйте значення, щоб налаштувати свій атрибут.

Для прикладу цього перегляньте AuthorizeAttribute у вихідному коді ASP.NET MVC за адресою www.codeplex.com/aspnet .


3
Можна навіть змусити MyCustomAttributeконструктора взяти масив рядків, a string[], з paramsмодифікатором або без нього . Тоді його можна застосувати із синтаксисом [MyCustom("CONTROL", "ALT", "SHIFT", "D")](with params).
Jeppe Stig Nielsen

2

Після додавання AttributeUsage переконайтеся, що ви додали це властивість до класу Attribute

public override object TypeId
{
  get
  {
    return this;
  }
}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.