C# .NET. Атрибуты. Роль атрибутов




Атрибуты. Роль атрибутов. Необходимость использования атрибутов. Пользовательские атрибуты


Содержание


Поиск на других ресурсах:

1. Что такое атрибуты? Зачем в программах используются атрибуты?

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

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

  • так называемые стандартные метаданные. Это метаданные, описывающие используемые в программе типы .NET (например SteamReader, FileStream и т.д.) и собственно разработанные типы (собственные классы, интерфейсы, структуры, делегаты, перечисления);
  • метаданные, получаемые с использованием так называемых атрибутов. Атрибуты позволяют дополнить тип (например, класс) дополнительными характеристиками декларативного характера. Атрибуты подобные аннотациям, которые прилагаются к программному коду и применяются к какому-то конкретному элементу программы. Атрибуты определяют поведение типов, к которым они присоединены.

С точки зрения реализации, атрибуты — это специально разработанные классы, которые являются производными от абстрактного класса System.Attribute.

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

В пространствах имен .NET доступен целый ряд предопределенных встроенных атрибутов, которые полезно применять в своих программах. Кроме того, программист имеет возможность создавать собственные (пользовательские) атрибуты.

На рисунке 1 изображен фрагмент сборки с метаданными, которые описывают присоединенные атрибуты.

Атрибуты. Дополнение сборки метаданными атрибутов

Рисунок 1. Дополнение сборки метаданными атрибутов

 

2. Создание и присоединение пользовательского атрибута. Общая форма

Любой пользовательский атрибут должен быть унаследован от класса System.Attribute. В наиболее общем случае, создание класса-атрибута имеет вид:

class MyClassAttribute : Attribute
{
  // ...
}

После того, как класс атрибута определен, он может быть присоединен к другому классу. Общая форма присоединения класса атрибута следующая

[MyClassAttribute(parameters)]
class MyClass
{
  // ...
}

здесь parameters – параметры конструктора класса атрибута.

Если конструктор класса атрибута не имеет параметров, то общая форма присоединения следующая

[MyClassAttribute]
class MyClass
{
  // ...
}

 

3. Требования и рекомендации при объявлении класса атрибута

Единственное требование при создании класса атрибута заключается в том, что класс должен быть унаследован от класса System.Attribute.

Кроме того, при использовании атрибутов в программах можно определить следующие рекомендации:

  • при объявлении класса атрибута, рекомендуется чтобы его имя заканчивалось суффиксом Attribute. Например, MyClassVersionAttribute, MyClassCommentAttribute и т.д.;
  • если к некоторому классу присоединяется атрибут, то указывать суффикс Attribute не обязательно. Например, если к классу MyClass присоединяется атрибут с именем MyClassCommentAttribute, то имя этого класса атрибута можно указать как MyClassComment убрав суффикс Attribute. Однако, если суффикс не убрать, ошибки также не будет.

 

4. Создание пользовательского класса атрибута на основе другого класса атрибута. Наследование атрибутов. Общая форма

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

[ AnotherClassAttribute1(parameters1),
  AnotherClassAttribute2(parameters2),
  ...
  AnotherClassAttribureN(parametersN)
]
class MyClassAttribute : Attribute
{
  // ...
}

здесь

  • AnotherClassAttribute1, AnotherClassAttribure2, AnotherClassAttribureN — имена классов атрибутов, которые присоединяются к пользовательскому классу атрибуту;
  • parameters1, parameters2, parametersN — параметры конструкторов присоединяемых классов атрибутов.

Если к классу атрибута присоединяется только один класс атрибут, то общая форма выглядит более упрощенно

[ AnotherClassAttribute(parameters) ]
class MyClassAttribute : Attribute
{
  // ...
}

 

5. Пример создания пользовательского класса-атрибута. Получение информации о классе атрибута

В примере демонстрируется создание пользовательского класса атрибута с именем MyClassCommentAttribute. Класс атрибута добавляет к элементу собственный комментарий (строку). Класс атрибута MyClassCommentAttribute присоединяется к классу MyClass. В функции main() продемонстрировано получение информации о классе атрибута, который присоединен к классу MyClass.

using System;

namespace ConsoleApp18
{
  // Объявление атрибута, содержащего комментарий
  class MyClassCommentAttribute : Attribute
  {
    private string comment; // базовое поле - комментарий

    // Конструктор
    public MyClassCommentAttribute(string _comment)
    {
      comment = _comment;
    }
  }

  // Объявление класса, к которому будет присоединяться атрибут.
  // Не обязательно указывать имя класса атрибута.
  [MyClassCommentAttribute("This is a my class.")]
  class MyClass
  {
    // Внутренние поля и методы класса
    // ...
  }

  class Program
  {
    static void Main(string[] args)
    {
      // Получить атрибуты класса MyClass
      // 1. Получить данные о типе MyClass
      Type tp = typeof(MyClass);

      // 2. Получить перечень атрибутов, которые присоединены к классу MyClass
      object[] attr = tp.GetCustomAttributes(false);

      // 3. Вывести имена атрибутов, присоединенных к MyClass
      Console.WriteLine("Attributes of class MyClass:");
      foreach (object o in attr)
      {
        Console.WriteLine(o.GetType().Name);
      }
      Console.ReadKey();
    }
  }
}

В вышеприведенном коде в строке, предшествующей объявлению класса MyClass

...
[MyClassCommentAttribute("This is a my class.")]
...

вызывается конструктор класса MyClassCommentAttribute, который в классе имеет следующее объявление

...

class MyClassCommentAttribute : Attribute
{
  ...

  // Конструктор
  public MyClassCommentAttribute(string _comment)
  {
    comment = _comment;
  }
}

В функции main() получается информация о присоединеных к классу MyClass атрибутах. В нашем случае это один атрибут MyClassCommentAttribute.

Сначала с помощью оператора typeof() получается экземпляр типа System.Type, который содержит данные о типе MyClass. На основе полученного экземпляра с помощью метода GetCustomAttributes() создается массив классов-атрибутов, который имеет тип object[]. Имена полученных классов-атрибутов выводятся в цикле foreach.

 


Связанные темы