Как создать повторяющиеся разрешенные атрибуты


96

Я использую настраиваемый атрибут, унаследованный от класса атрибутов. Я использую это так:

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

}

Но отображается ошибка «Дублировать атрибут MyCustomAttribute».
Как я могу создать повторяющийся разрешенный атрибут?

Ответы:


185

Придерживайтесь AttributeUsageатрибутом на класс Attribute (Да, это полный рот) и набор AllowMultipleдля true:

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

6
Просто любопытно - почему «закрытый» класс?
Томас Ашан,

18
Microsoft рекомендует по возможности закрывать
Антон Гоголев,

3
Почему запечатано? Вкратце: ускоряет поиск атрибутов и не оказывает никакого другого влияния.
Ноэль Видмер

За исключением того, что это мешает кому-либо повторно использовать ваш код. Стоит отметить, что атрибуты валидации в DataAnnotations не запечатаны, что чрезвычайно полезно, поскольку позволяет создавать их специализации.
Neutrino

@Neutrino sealed следует использовать всякий раз, когда вы не ожидаете или не планируете создавать свои классы для наследования. Плюс, когда наследование может стать источником ошибок ex: Thread-safe реализации.
Франсиско Нето,

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

9

По умолчанию 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")]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.