Поиск по сайту:

Как работают атрибуты в C#?


В C# атрибуты — это теги метаданных, назначенные коду, включая классы, типы, методы и поля. Используя отражение, вы можете исследовать теги, чтобы изменить поведение в вашей программе. Мы покажем, как их использовать и как написать свой собственный.

Что такое атрибуты?

Проще говоря, атрибуты — это теги метаданных, которые содержат некоторую информацию. Синтаксис для них — это имя типа в квадратных скобках над помечаемым кодом, например:

[Attribute]
void Command() 
{

Они могут быть присоединены практически к чему угодно — классам, методам, полям, структурам, типам и т. д. Им даже могут быть заданы параметры для предоставления входных данных, к которым можно получить доступ, хотя они ограничены базовыми типами. Вы можете установить параметры, вызвав атрибут как метод:

[Attribute("name", Test=false, Number=42)]

Распространенным вариантом использования является маркировка полей для сериализации. C# имеет встроенный тег [Serializable] , который поддерживает сериализацию класса в байты, и многие сторонние библиотеки реализуют свои собственные теги. Например, драйвер C# для MongoDB включает множество тегов для сериализации в Bson, а также специальный тег, который интерпретирует строку как идентификатор документа.

Другим распространенным вариантом использования является пометка методов, которые управляются обработчиком команд более высокого уровня. Например, бот Discord регистрирует список команд, которые обрабатываются всякий раз, когда кто-то отправляет сообщение. Вместо того, чтобы вручную добавлять каждую команду в обработчик команд каждый раз, когда вы пишете новую, вы можете пометить метод тегом [Command(\commandname\)] и использовать универсальное решение, которое добавить их все автоматически во время выполнения.

Вы можете прочитать документацию Microsoft, чтобы узнать больше, но они довольно просты.

Как сделать свои собственные атрибуты

Конечно, вы можете довольно легко создать свои собственные настраиваемые атрибуты для применения к вашим классам. Все, что вам нужно сделать, это создать класс, который наследуется от System.Attribute. Вы также можете добавить в этот класс атрибут, указывающий, как его следует использовать; например, применяя только к классам или структурам.

Затем вы можете указать поля и конструктор, который будет принимать входные параметры и заполнять поля. Когда вы используете этот атрибут, это похоже на вызов new Attribute(params), за исключением того, что без ключевого слова new.

[System.AttributeUsage(System.AttributeTargets.Class | System.AttributeTargets.Struct)]  
public class AuthorAttribute : System.Attribute  
{  
    private string name;  
    public double version;  
  
    public AuthorAttribute(string name)  
    {  
        this.name = name;  
        version = 1.0;  
    }  
}

Затем вы можете использовать их для маркировки своего кода при условии, что на атрибут есть ссылка в помечаемом коде.

Для программного доступа к атрибутам вам потребуется использовать отражение. Отражение не очень хорошо влияет на производительность, но для вариантов использования атрибутов это обычно не имеет значения. Вы можете использовать Attribute.GetCustomAttributes, чтобы вернуть Attribute[], передав тип класса:

System.Attribute.GetCustomAttributes(typeof(className));

Если вы хотите получить доступ ко всем экземплярам атрибутов в своей сборке, вы можете использовать Assembly.GetExecutingAssembly().GetTypes(), чтобы получить список исполняемых типов, а затем проверить все пользовательские атрибуты этого типа, чтобы посмотрите, содержит ли он параметр поиска, при необходимости отфильтровав этот список на основе типа класса, к которому прикреплен атрибут.

var plugins = Assembly.GetExecutingAssembly().GetTypes()
    .Where(t => t.IsClass 
            && t.BaseType == typeof(BasePlugin) 
            && Attribute.GetCustomAttributes(t).Any((atr) => atr.GetType() == typeof(MyCustomAttribute)))
    .ToList();

Чтобы получить доступ к параметрам атрибута, вы просто обращаетесь к ним непосредственно из класса Attribute, как и к любым другим общедоступным свойствам.