Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Лабораторные работы Java и C# технологии.doc
Скачиваний:
171
Добавлен:
01.03.2016
Размер:
3.04 Mб
Скачать
        1. Использование встроенных атрибутов

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

  1. Создать метод, использующий атрибут (например, метод, при каждом вызове которого компилятор будет формировать сообщение Warningс указанным в атрибуте кодом);

  2. Ввести перед определением метода в квадратных скобках имя класса атрибута (например, класса ObsoleteAttribute).

Например, встроенный класс System.ObsoleteAttributeпозволяет помечать код и задавать информацию, например, "Будет удалено в следующей версии", которая будет отображаться какWarningво время компиляции приложения. Этот класс предназначается для возможности указания некоторого кода модуля как "устаревшего".

public class MainApp

{ public static void Main()

{ //На этой строке компилятор выдаст предупреждение

int MyInt = Add(2,2);

}

//Этот атрибут применяется только к методу Add

[Obsolete("В следующей версии метод будет удален")]

public static int Add(int a, int b)

{ return (a + b);

}

}

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

c:\c#_project\pr1\ MainApp.cs(23,4): warning

CS0618: 'pr1. MainApp.Add()' is obsolete:

' В следующей версии метод будет удален '

Для применения атрибутов на уровне сборок используется ключевое слово Assembly. Следующий пример показывает, как используется атрибутAssemblyNameAttribute:

using System.Reflection;

[assembly:AssemblyName("Моя сборка")]

При компиляции кода строка "Моя сборка" помещается в манифест сборки в секции метаданных. Этот атрибут можно увидеть с помощью дизассемблера MSIL (Ildasm.exe) или с помощью пользовательских средств.

Для применения атрибутов на уровне модулей используется ключевое слово Module, в остальном все как на уровне сборок.

using System.Reflection;

[module:ModuleName("Мой модуль")]

        1. Определение и использование пользовательских атрибутов

Создание атрибута начинается с создания класса, реализующего атрибут. Такой класс должен быть наследуем от любого класса атрибута. Класс атрибута всегда должен иметь модификатор доступа public. Класс атрибута всегда непосредственно или опосредованно наследуется от классаSystem.Attribute.

Объявление пользовательского атрибута начинается со встроенного атрибута AttributeUsageAttribute, который задает ключевые характеристики нового класса. Например, он определяет, может ли атрибут наследоваться другими классами, или к каким элементам он может применяться. Следующий фрагмент кода иллюстрирует применение атрибутаAttributeUsageAttribute

[AttributeUsage(AttributeTargets.All, Inherited = false,

AllowMultiple = true)]

Класс System.AttributeUsageAttributeсодержит три члена, которые важны для создания пользовательских атрибутов. Это поля:AttributeTargets,InheritedиAllowMultiple.

Поле AttributeTargets

В предыдущем примере используется флаг AttributeTargets.All. Этот флаг означает, что данный атрибут может применяться к любым элементам программы. С другой стороны, можно задать флагAttributeTargets.Class, означающий, что атрибут применяется только к классам, илиAttributeTargets.Method– для методов классов и интерфейсов. Подобным образом можно применять и пользовательские атрибуты.

Также можно использовать несколько экземпляров атрибута AttributeTargets. В следующем примере показано, как пользовательский атрибут может применяться к любому классу или методу:

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]

Свойство Inheritedопределяет, будет ли атрибут наследоваться классами, наследниками того, к которому этот атрибут применен. Это свойство может принимать два значения:trueилиfalse. По умолчаниюInherited = true.

Свойство AllowMultiple

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

Ниже приведен пример создания собственного атрибута.

using System;

namespace test

{ //Объявление атрибута

[AttributeUsage(AttributeTargets.All, Inherited = false,

AllowMultiple = true)]

public class TestAttribute: System.Attribute

{ //Поле атрибута

private string name;

private int kod;

//Свойство Name только для чтения

public virtual string Name

{ get

{ return name;

}

}

// Свойство Kod

public int Kod

{ get { return kod; }

set {kod = value; } // Назначение защищенной переменной

// класса значения параметра

}

//Конструктор атрибута

public TestAttribute(string name)

{ this.name = name;

this.kod = 12345;

}

}

//Конец объявления атрибута

Как видно, атрибут TestAttributeявляется потомком классаSystem.Attribute. Перед определением нового атрибутаTestAttributeмы видим строку, которая определяет область применения этого атрибута

[AttributeUsage(AttributeTargets.All, Inherited = false,

AllowMultiple = true)]

Далее мы определяем для нашего атрибута внутренние переменные nameтипаstringиkodтипаint.

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

Затем определяется конструктор с параметром nameтипаstring. В конструкторе мы записываем значение в полеname.

Конструкторы атрибутивного класса можно перегружать, чтобы принимать различные комбинации параметров. Если для атрибутивного класса определены свойства, в нашем примере NameиKod, для инициализации конструктора можно использовать комбинациюпозиционныхиименованныхпараметров. Обычно все обязательные параметры объявляются как позиционные, а необязательные как именованные.

После создания класса атрибута мы применяем его к другому классу Test. Для этого в коде мы должны создать экземпляр атрибутаTestAttributeнепосредственно перед классомTest. В нашем случае возможны два варианта задания атрибута – только с позиционным параметром

[TestAttribute("Hallow Word")]

или с позиционным и именованным параметром

[TestAttribute("Hallow Word"), Kod=123]

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

//Применение атрибута к классу

[TestAttribute("Hallow Word", Kod=123)] //Вызывается конструктор атрибута

class Test

{ static void Main()

{ // Вызвать функцию получения и отображения атрибута

GetAttribute(typeof(Test));

}

public static void GetAttribute(Type t)

{ //Получение экземпляра атрибута TestAttribute класса Test

TestAttribute att=

(TestAttribute) Attribute.GetCustomAttribute(t,

typeof(TestAttribute));

//Получение и вывод свойства атрибута TestAttribute

Console.WriteLine("{0}", att.Name);

}

}

}

В классе Testв методеGetAttributeна консоль выводится значение свойстваNameэтого атрибута. Для этого мы воспользовались статическим методомGetCustomAttributeклассаAttribute. Этот метод принимает в качестве параметров тип Test, к которому применяется атрибут, и собственно применяемый атрибутTestAttribute. Метод возвращает экземпляр атрибута, который используется для получения значения свойстваName.

Метод GetAttributeвызываем в статическом методеMain.

Результатом выполнения программы будет вывод на консоль слов "HallowWord".