Язык программирования C#9 и платформа .NET5
В идеальном случае к настоящему моменту вы уже должны понимать перечисленные ниже ключевые моменты, касающиеся атрибутов .NET Core:
• атрибуты представляют собой классы, производные от
;System.Attribute• атрибуты дают в результате встроенные метаданные;
• атрибуты в основном бесполезны до тех пор, пока другой агент не проведет в их отношении рефлексию;
• атрибуты в языке C# применяются с использованием квадратных скобок.
А теперь давайте посмотрим, как реализовывать собственные специальные атрибуты и создавать специальное программное обеспечение, которое выполняет рефлексию по встроенным метаданным.
Построение специальных атрибутов
Первый шаг при построении специального атрибута предусматривает создание нового класса, производного от
. Не отклоняясь от автомобильной темы, повсеместно встречающейся в книге, создайте новый проект типа Class Library (Библиотека классов) на C# под названиемSystem.Attribute. В этой сборке будет определено несколько классов для представления транспортных средств, каждый из которых описан с использованием специального атрибута по имениAttributedCarLibrary:VehicleDescriptionAttributeusing System;// Специальный атрибут.public sealed class VehicleDescriptionAttribute :Attribute{public string Description { get; set; }public VehicleDescriptionAttribute(string description)=> Description = description;public VehicleDescriptionAttribute(){ }}Как видите, класс
поддерживает фрагмент строковых данных, которым можно манипулировать с помощью автоматического свойства (VehicleDescriptionAttribute). Помимо того факта, что данный класс является производным отDescription, ничего примечательного в его определении нет.System.AttributeНа заметку! По причинам, связанным с безопасностью, установившейся практикой в .NET Core считается проектирование всех специальных атрибутов как запечатанных. На самом деле среды Visual Studio и Visual Studio Code предлагают фрагмент кода под названием
, который позволяет сгенерировать в окне редактора кода новый класс, производный отAttribute. Для раскрытия любого фрагмента кода необходимо набрать его имя и нажать клавишу <ТаЬ> (один раз в Visual Studio Code и два раза в Visual Studio).System.AttributeПрименение специальных атрибутов
С учетом того, что класс
является производным отVehicleDescriptionAttribute, теперь можно аннотировать транспортные средства. В целях тестирования добавьте в новую библиотеку классов следующие файлы классов:System.Attribute// Motorcycle.csnamespace AttributedCarLibrary{// Назначить описание с помощью "именованного свойства".[Serializable][VehicleDescription(Description = "My rocking Harley")]// Мой покачивающийся Харлиpublic class Motorcycle{}// HorseAndBuggy.csnamespace AttributedCarLibrary{[Serializable][Obsolete ("Use another vehicle!")][VehicleDescription("The old gray mare, she ain't what she used to be...")]// Старая серая лошадка, она уже не та...public class HorseAndBuggy{}}// Winnebago.csnamespace AttributedCarLibrary{[VehicleDescription("A very long, slow, but feature-rich auto")]// Очень длинный, медленный, но обладающий высокими// техническими характеристиками автомобильpublic class Winnebago{}}Синтаксис именованных свойств
Обратите внимание, что классу
назначается описание с использованием нового фрагмента синтаксиса, связанного с атрибутами, который называется именованным свойством. В конструкторе первого атрибутаMotorcycleлежащие в основе строковые данные устанавливаются с применением свойства[VehicleDescription]. Когда внешний агент выполнит рефлексию для этого атрибута, свойствуDescriptionбудет передано указанное значение (синтаксис именованных свойств разрешен, только если атрибут предоставляет поддерживающее запись свойство .NET Core).DescriptionПо контрасту для типов
иHorseAndBuggyсинтаксис именованных свойств не используется, а строковые данные просто передаются через специальный конструктор. В любом случае после компиляции сборкиWinnebagoс помощью утилитыAttributedCarLibraryможно просмотреть добавленные описания метаданных. Например, ниже показано встроенное описание классаildasm.exe:Winnebago// CustomAttribute #1// -------------------------------------------------------

