Чтение онлайн

ЖАНРЫ

Язык программирования C#9 и платформа .NET5
Шрифт:

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

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

Как нетрудно догадаться, в состав .NET Core входят многочисленные утилиты, которые действительно ищут разнообразные атрибуты. Сам компилятор C# (

csc.exe
)
запрограммирован на обнаружение различных атрибутов при проведении компиляции. Например, встретив атрибут
[CLSCompilant]
, компилятор автоматически проверяет помеченный им элемент и удостоверяется в том, что в нем открыт доступ только к конструкциям, совместимым с CLS. Еще один пример: если компилятор обнаруживает элемент с атрибутом
[Obsolete]
, тогда он отображает в окне Error List (Список ошибок) среды Visual Studio сообщение с предупреждением.

В дополнение к инструментам разработки многие методы в библиотеках базовых классов . NET Core изначально запрограммированы на распознавание определенных атрибутов посредством рефлексии. В главе 20 рассматривается сериализация XML и JSON, которая задействует атрибуты для управления процессом сериализации.

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

Применение атрибутов в C#

Чтобы ознакомиться со способами применения атрибутов в С#, создайте новый проект консольного приложения по имени

ApplyingAttributes
и добавьте ссылку на
System.Text.Json
. Предположим, что необходимо построить класс под названием
Motorcycle
(мотоцикл), который может сохраняться в формате JSON. Если какое-то поле сохраняться не должно, тогда к нему следует применить атрибут
[JsonIgnore]
.

public class Motorcycle

{

[JsonIgnore]

public float weightOfCurrentPassengers;

// Эти поля остаются сериализируемыми.

public bool hasRadioSystem;

public bool hasHeadSet;

public bool hasSissyBar;

}

На заметку! Атрибут применяется только к элементу, находящемуся непосредственно после него.

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

Нетрудно догадаться, что к одиночному элементу можно применять множество атрибутов. Предположим, что у вас есть унаследованный тип класса C# (

НоrseAndBuggy
), который был снабжен атрибутом, чтобы иметь специальное пространство имен XML. Со временем кодовая база изменилась, и класс теперь считается устаревшим для текущей разработки. Вместо того чтобы удалять определение такого класса из кодовой базы (с риском нарушения работы существующего программного обеспечения), его можно пометить атрибутом
[Obsolete]
. Для применения множества атрибутов к одному элементу просто используйте список с разделителями-запятыми:

using System;

using System.Xml.Serialization;

namespace ApplyingAttributes

{

[XmlRoot(Namespace = "http://www.MyCompany.com"),

Obsolete("Use another vehicle!")]

//
Используйте другое транспортное средство!

public class HorseAndBuggy

{

// ...

}

}

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

[XmlRoot(Namespace = "http://www.MyCompany.com")]

[Obsolete("Use another vehicle!")]

public class HorseAndBuggy

{

// ...

}

Сокращенная система обозначения атрибутов C#

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

[Obsolete]
, является
ObsoleteAttribute
, а не просто
Obsolete
. По соглашению имена всех атрибутов .NET Core (включая специальные атрибуты, которые создаете вы сами) снабжаются суффиксом
Attribute
. Тем не менее, чтобы упростить процесс применения атрибутов, в языке C# не требуется обязательный ввод суффикса
Attribute
. Учитывая это, показанная ниже версия типа
HorseAndBuggy
идентична предыдущей версии (но влечет за собой более объемный клавиатурный набор):

[SerializableAttribute]

[ObsoleteAttribute("Use another vehicle!")]

public class HorseAndBuggy

{

// ...

}

Имейте в виду, что такая сокращенная система обозначения для атрибутов предлагается только в С#. Ее поддерживают не все языки .NET Core.

Указание параметров конструктора для атрибутов

Обратите внимание, что атрибут

[Obsolete]
может принимать то, что выглядит как параметр конструктора. Если вы просмотрите формальное определение атрибута
[Obsolete]
, щелкнув на нем правой кнопкой мыши в окне кода и выбрав в контекстном меню пункт Go То Definition (Перейти к определению), то обнаружите, что данный класс на самом деле предоставляет конструктор, принимающий
System.String
:

public sealed class ObsoleteAttribute : Attribute

{

public ObsoleteAttribute(string message, bool error);

public ObsoleteAttribute(string message);

public ObsoleteAttribute;

public bool IsError { get; }

public string? Message { get; }

}

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

Поделиться с друзьями: