В платформе .NET, и, следовательно, в Visual Basic, атрибуты были введены как мощный инструмент для аннотирования различных элементов кода метаданными. Это позволяет программам и инструментам на этапе исполнения и компиляции получать дополнительную информацию, настраивать поведение методов, классов, свойств через механизмы рефлексии, сериализации, автоматизации тестирования и так далее.
Без атрибутов приходится жёстко кодировать дополнительную логику для настройки методов или классов, а универсальные библиотеки не могут быть расширяемыми и гибкими без внешней информации о классе или методе. Возникает также проблема передачи настроек без изменения самого кода.
Атрибуты — специальные классы-наследники Attribute. Их можно создавать и применять к методам, классам, свойствам, параметрам или возвращаемым значениям. На этапе исполнения эти атрибуты можно обнаружить через рефлексию и изменить поведение соответствующей логики.
Пример кода создания и использования собственного атрибута:
Imports System <AttributeUsage(AttributeTargets.Class Or AttributeTargets.Method, AllowMultiple:=False)> Public Class InfoAttribute Inherits Attribute Public Property Description As String Public Sub New(desc As String) Description = desc End Sub End Class <Info("Special business logic method.")> Public Sub Calculate() Console.WriteLine("Calculation performed.") End Sub ' Чтение атрибута через рефлексию Dim method = GetType(Module1).GetMethod("Calculate") Dim attr = CType(Attribute.GetCustomAttribute(method, GetType(InfoAttribute)), InfoAttribute) If attr IsNot Nothing Then Console.WriteLine(attr.Description)
Ключевые особенности:
AttributeTargets.Class, Method, Property и др.)Могут ли атрибуты напрямую изменить поведение метода или класса без использования рефлексии?
Нет, сами по себе атрибуты содержат только метаданные. Изменить поведение объекта можно только, если вызывающий код или рантайм проверяет наличие атрибута через рефлексию и предпринимает дополнительные действия.
Можно ли назначить один и тот же атрибут несколько раз на один и тот же элемент, и что для этого требуется?
По умолчанию — нет. Для этого при объявлении атрибута нужно указать AllowMultiple:=True в AttributeUsage. Тогда можно применять один атрибут несколько раз к одному элементу.
Наследуются ли атрибуты от базового класса к производному?
Нет, по умолчанию — не наследуются. Если требуется наследование, в AttributeUsage указывается параметр Inherited:=True.
В проекте массово расставляются кастомные атрибуты для методов, но никто не реализует обработку этих атрибутов через рефлексию — такой код становится бесполезным балластом, затрудняющим поддержку и усложняющим чтение исходников.
Плюсы:
Минусы:
Атрибут применяется для аннотирования методов логирования, и отдельная подсистема через рефлексию автоматически определяет, какие методы подлежат аудиту, подставляет аналитику, добавляет трейсинг. Поведение прозрачно для пользователя.
Плюсы:
Минусы: