Атрибуты

81

В C# разрешается вводить в программу информацию декларативного характера в форме атрибута, с помощью которого определяются дополнительные сведения (метаданные), связанные с классом, структурой, методом и т.д. Например, в программе можно указать атрибут, определяющий тип кнопки, которую должен отображать конкретный класс. Атрибуты указываются в квадратных скобках перед тем элементом, к которому они применяются. Следовательно, атрибут не является членом класса, но обозначает дополнительную информацию, присоединяемую к элементу.

Одной из задач компилятора .NET является генерирование описаний метаданных для всех типов, которые были определены, и на которые имеется ссылка в текущем проекте. Помимо стандартных метаданных, которые помещаются в любую сборку, программисты в .NET могут включать в состав сборки дополнительные метаданные с использованием атрибутов. В сущности, атрибуты представляют собой не более чем просто аннотации, которые могут добавляться в код и применяться к какому-то конкретному типу (классу, интерфейсу, структуре и т.д.), члену (свойству, методу и т.д.), сборке или модулю.

Концепция аннотирования кода с применением атрибутов является далеко не новой. Еще в COM IDL (Interface Definition Language — язык описания интерфейсов) поставлялось множество предопределенных атрибутов, которые позволяли разработчикам описывать типы, содержащиеся внутри того или иного СОМ-сервера. Однако в СОМ атрибуты представляли собой немногим более чем просто набор ключевых слов. Когда требовалось создать специальный атрибут, разработчик в СОМ мог делать это, но затем он должен был ссылаться на этот атрибут в коде с помощью 128-битного числа (GUID-идентификатора), что, как минимум, довольно затрудняло дело.

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

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

[CLSCompliant]

Заставляет элемент, к которому применяется, отвечать требованиям CLS (Common Language Specification — общеязыковая спецификация). Вспомните, что типы, которые отвечают требованиям CLS, могут без проблем использоваться во всех языках программирования .NET

[DllImport]

Позволяет коду .NET отправлять вызовы в любую неуправляемую библиотеку кода на С или С++, в том числе и API-интерфейс лежащей в основе операционной системы. Обратите внимание, что при взаимодействии с программным обеспечением, работающим на базе СОМ, этот атрибут не применяется

[Obsolete]

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

[Serializable]

Позволяет указать, что класс или структура является "сериализируемой", т.е. способна сохранять свое текущее состояние в потоке

[NonSerialized]

Позволяет указать, что данное поле в классе или структуре не должно сохраняться в процессе сериализации

[WebMethod]

Позволяет указать, что метод может вызываться посредством HTTP-запросов, и CLR-среда должна преобразовывать его возвращаемое значение в формат XML

Важно уяснить, что при применении атрибутов в коде размещающиеся внутри них метаданные, по сути, остаются бесполезными до тех пор, пока не запрашиваются явным образом в каком-то другом компоненте программного обеспечения посредством рефлексии. Если этого не происходит, они спокойно игнорируются и не причиняют никакого вреда.

Потребители атрибутов

Как нетрудно догадаться, в составе NET Framework 4.0 SDK поставляется множество утилит, которые позволяют производить поиск разнообразных атрибутов. Даже сам компилятор C# (csc.ехе) запрограммирован так, что он проверяет наличие разных атрибутов во время компиляции. Например, сталкиваясь с атрибутом [CLSCompilant], он автоматически проверяет соответствующий элемент и удостоверяется в том, что в нем содержатся только отвечающие требованиям CLS инструкции, а при обнаружении элемента с атрибутом [Obsolete] отображает внутри окна ErrorList (Список ошибок) в Visual Studio 2010 соответствующее предупреждение.

Помимо утилит, предназначенных для использования во время разработки, многие методы в библиотеках базовых классов .NET тоже изначально запрограммированы так, чтобы распознавать определенные атрибуты посредством рефлексии. Например, чтобы информация о состоянии объекта сохранялась в файле, все, что потребуется делать — это просто добавить в класс или структуру в виде аннотации атрибут [Serializable]. Встретив этот атрибут, метод Serialize() из класса BinaryFormatter автоматически сохраняет соответствующий объект в файле в компактном двоичном формате.

CLR-среда в .NET тоже выполняет проверки на предмет наличия определенных атрибутов. Самым известным из них, пожалуй, является атрибут [WebMethod], который применяется для создания веб-служб XML с помощью ASP.NET. Чтобы можно было получать доступ к методу посредством HTTP-запросов, а его возвращаемое значение автоматически преобразовывалось в формат XML, понадобится применить к этому методу атрибут [WebMethod], а обо всех остальных деталях будет заботиться CLR-среда. Помимо разработки веб-служб, атрибуты также играют важную роль в функционировании системы безопасности .NET, в Windows Communication Foundation, в обеспечении функциональной совместимости между СОМ и .NET, и во многом другом.

И, наконец, допускается разрабатывать приложения, способные распознавать специальные атрибуты, а также любые из тех, что поставляются в составе библиотек базовых классов .NET. Это позволяет, по сути, создавать набор "ключевых слов", понятных только определенному множеству сборок.

Пройди тесты
Лучший чат для C# программистов