Поделиться через


Атрибуты

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

Атрибуты имеют следующие свойства:

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

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

Ниже приведен простой пример отражения с помощью метода GetType() , унаследованного всеми типами из базового класса Object, чтобы получить тип переменной:

Заметка

Убедитесь, что вы добавите using System; и using System.Reflection; в верхней части файла .cs.

// Using GetType to obtain type information:
int i = 42;
Type type = i.GetType();
Console.WriteLine(type);

Выходные данные: System.Int32.

В следующем примере используется отражение для получения полного имени загруженной сборки.

// Using Reflection to get information of an Assembly:
Assembly info = typeof(int).Assembly;
Console.WriteLine(info);

Выходные данные примерно такие: System.Private.CoreLib, Version=7.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e.

Заметка

Ключевые слова C# protected и internal не имеют значения в промежуточном языке (IL) и не используются в API отражения. Соответствующие термины в IL — это семейства и сборки. Чтобы определить метод internal с помощью отражения, используйте свойство IsAssembly. Чтобы определить метод protected internal, используйте IsFamilyOrAssembly.

Использование атрибутов

Атрибуты можно поместить почти в любое объявление, хотя определенный атрибут может ограничить типы объявлений, для которых он действителен. В C#можно указать атрибут, поместив имя атрибута, заключенного в квадратные скобки ([]) над объявлением сущности, к которой она применяется.

В этом примере атрибут SerializableAttribute используется для применения определенной характеристики к классу:

[Serializable]
public class SampleClass
{
    // Objects of this type can be serialized.
}

Метод с атрибутом DllImportAttribute объявлен следующим образом:

[System.Runtime.InteropServices.DllImport("user32.dll")]
extern static void SampleMethod();

Несколько атрибутов можно поместить в объявление, как показано в следующем примере:

void MethodA([In][Out] ref double x) { }
void MethodB([Out][In] ref double x) { }
void MethodC([In, Out] ref double x) { }

Некоторые атрибуты можно указать несколько раз для определенной сущности. Примером такого многопользовательского атрибута является ConditionalAttribute:

[Conditional("DEBUG"), Conditional("TEST1")]
void TraceMethod()
{
    // ...
}

Заметка

По соглашению все имена атрибутов заканчиваются словом "Атрибут", чтобы отличить их от других элементов в библиотеках .NET. Однако при использовании атрибутов в коде не требуется указывать суффикс атрибутов. Например, [DllImport] эквивалентен [DllImportAttribute], но DllImportAttribute является фактическим именем атрибута в библиотеке классов .NET.

Параметры атрибута

Многие атрибуты имеют параметры, которые могут быть позициональными, неназванными или именованными. Любые позиционные параметры должны быть указаны в определенном порядке и не могут быть опущены. Именованные параметры являются необязательными и могут быть указаны в любом порядке. Сначала задаются позиционные параметры. Например, эти три атрибута эквивалентны:

[DllImport("user32.dll")]
[DllImport("user32.dll", SetLastError=false, ExactSpelling=false)]
[DllImport("user32.dll", ExactSpelling=false, SetLastError=false)]

Первый параметр, имя библиотеки DLL, позиционный и всегда приходит первым; другие называются. В этом случае оба именованных параметра по умолчанию используют значение false, поэтому они могут быть опущены. Позиционные параметры соответствуют параметрам конструктора атрибутов. Именованные или необязательные параметры соответствуют свойствам или полям атрибута. Сведения о значениях параметров по умолчанию см. в документации по отдельным атрибутам.

Дополнительные сведения о разрешенных типах параметров см. в разделе Атрибуты спецификации языка C#.

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

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

Чтобы явно определить целевой объект атрибута, используйте следующий синтаксис:

[target : attribute-list]

Список возможных значений target показан в следующей таблице.

Целевое значение Применимо к
assembly Вся сборка
module Текущий модуль сборки
field Поле в классе или структуре
event Событие
method Метод или методы доступа к свойствам get и set
param Параметры метода или параметры аксессоров свойств set
property Свойство
return Возвращаемое значение метода, индексатора свойств или метода доступа к свойствам get
type Структура, класс, интерфейс, перечисление или делегат

Можно указать целевое значение field, чтобы применить атрибут к резервному полю, созданному для автоматически реализованных свойств.

В следующем примере показано, как применять атрибуты к сборкам и модулям. Дополнительные сведения см. в разделе «Общие атрибуты (C#)».

using System;
using System.Reflection;
[assembly: AssemblyTitleAttribute("Production assembly 4")]
[module: CLSCompliant(true)]

В следующем примере показано, как применять атрибуты к методам, параметрам метода и возвращаемым значениям метода в C#.

// default: applies to method
[ValidatedContract]
int Method1() { return 0; }

// applies to method
[method: ValidatedContract]
int Method2() { return 0; }

// applies to parameter
int Method3([ValidatedContract] string contract) { return 0; }

// applies to return value
[return: ValidatedContract]
int Method4() { return 0; }

Заметка

Независимо от целевых объектов, для которых определена допустимая ValidatedContract, необходимо указать целевой объект return, даже если ValidatedContract были определены для применения только к возвращаемым значениям. Другими словами, компилятор не будет использовать информацию AttributeUsage для разрешения неоднозначных целевых атрибутов. Дополнительные сведения см. в разделе AttributeUsage.

Распространенные способы использования атрибутов

В следующем списке приведены некоторые распространенные способы использования атрибутов в коде:

  • Пометка методов с помощью атрибута WebMethod в веб-службах, чтобы указать, что метод должен вызываться по протоколу SOAP. Дополнительные сведения см. в WebMethodAttribute.
  • Как осуществлять маршалирование параметров метода при взаимодействии с нативным кодом. Дополнительные сведения см. в MarshalAsAttribute.
  • Описание свойств COM для классов, методов и интерфейсов.
  • Вызов неуправляемого кода с помощью класса DllImportAttribute.
  • Описание сборки с точки зрения названия, версии, описания или торговой марки.
  • Описание элементов класса, подлежащих сериализации для устойчивости.
  • Описание сопоставления между членами класса и XML-узлами для сериализации XML.
  • Описание требований безопасности для методов.
  • Указание характеристик, используемых для обеспечения безопасности.
  • Управление оптимизацией с помощью JIT-компилятора, чтобы код оставался простым для отладки.
  • Получение сведений о вызывающем методе.

Обзор рефлексии

Отражение полезно в следующих ситуациях:

Дополнительные сведения: