Язык программирования Перфолента.Net - Официальный сайт

 Язык программирования Перфолента.Net - Официальный сайт.

Поиск   
Главная :: О проекте :: Контакты :: Обратная связь :: Благодарности :: ВходГость

   >   >   >   > 



Атрибуты элементов программы

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


Как и атрибуты в обычной жизни, атрибуты элементов программы могут рассказать о хозяине что-то интересное.

«Атрибут - это как наклейка на коробке,

на которой написана дополнительная информация.»

 

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

Атрибут - это как наклейка на коробке, на которой написана дополнительная информация.

Думаете я зря это повторил? Нет! В этом вся суть атрибутов – они дают дополнительную информацию о классе, структуре, поле, методе, параметре метода и о любом другом элементе программы к которому прикреплены.

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

Процесс получения атрибутов сборки и других элементов программы называется рефлексией (reflection).

 

Виды атрибутов.

Часть используемых вами атрибутов определена прямо в языке Перфолента. Это атрибуты видимости, наследования, переопределения методов и другие. С каждым из них мы познакомимся чуть позже.

Некоторые атрибуты определены в библиотеке Net Framework и могут использоваться компиляторами любых .Net языков. Другие определены в стандартной библиотеке Перфоленты и могут использоваться компилятором Перфоленты и программами, использующими эту библиотеку. А некоторые атрибуты будут определены Вами в вашей программе и использовать их будете только Вы.

Умнику на заметку: в языке 1С, как и в некоторых других языках программирования, атрибуты называют аннотациями. В разных языках синтаксис записи атрибутов (аннотаций) различен, как и способы их использования, но в большинстве современных языков они в том или ином виде есть.

 

Устройство атрибута.

Технически, атрибуты — это специальные классы, унаследованные от класса Атрибут, который в .Net соответствует классу System.Attribute.

Атрибуты могут что-то значить сами по себе или иметь конструктор, принимающий на хранение дополнительную информацию в виде параметров.  Типы параметров конструктора атрибута, а также полей и свойств, ограничены в .Net следующими типами: Цел8, Цел32, Цел64, Байт, Бит32, Бит64, Вещ, ДВещ, Строка, Символ, Булево, Тип, а также это может быть Перечисление одного из указанных типов.

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

 

Определим простейший атрибут:

&ВидноВсем
Класс АнглийскийСиноним Родитель Атрибут
        Поле _Синоним тип Строка

        &ВидноВсем
        Конструктор(Синоним тип Строка)
                _Синоним = Синоним
        КонецКонструктора
        &ВидноВсем
        Функция ПолучитьСиноним() тип Строка
                Возврат _Синоним
        КонецФункции
КонецКласса

Как видим, кроме наследования от типа Атрибут, других особенностей у класса-атрибута нет.

Используем созданный нами атрибут для одного из методов программы:

&АнглийскийСиноним("Start"), ВидноВсем
Процедура Старт
        //тут какой-то код
КонецПроцедуры

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

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

 

Синтаксис атрибута.

Элемент программы может иметь один или несколько атрибутов.

Формальный синтаксис атрибута выглядит так:

&[Новый] ИмяАтрибута[(ПараметрКонструктора1, …, ПараметрКонструктораН)][{ .СвойствоАтрибута1=ЗначениеАтрибута1, …, . СвойствоАтрибутаН=ЗначениеАтрибутаН}]

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

Например, в объявлении процедуры Старт, которое было показано выше, у атрибута ВидноВсем в наличии только имя, а у атрибута АнглийскийСиноним в наличии один фактический параметр конструктора.

 

Синтаксис списка атрибутов.

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

&Атрибут1, Атрибут2, АтрибутН   ЭлементПрограммы...

&Атрибут1 &Атрибут2 &АтрибутН   ЭлементПрограммы...

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

&Атрибут1,
Атрибут2,
АтрибутН
ЭлементПрограммы...

&Атрибут1
&Атрибут2
&АтрибутН
ЭлементПрограммы...

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

В конструктор атрибута можно передать необходимое количество параметров (в данном случае один):

&Новый АнглийскийСиноним ("MyClass")

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

&АнглийскийСиноним ("MyClass")

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

&Новый ИмпортМетода("kernel32.dll"){ .EntryPoint="SetConsoleTitleW", .CharSet=CharSet.Auto, .SetLastError=True}

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

//в этом атрибуте проверим вычисление константных выражений в параметрах
&EnumerationType("Виды"+"Операци"+"и"с,   "Operation"+"Types",   Не Ложь)

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

&Новый ВидноВсем(){}, Новый ВидноСборке(){}

Пустые круглые и фигурные скобки, как и ключевое слово Новый не обязательны:

&ВидноВсем, ВидноСборке

 

Встроенные атрибуты языка Перфолента.

 

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

ВидноВсем, ВидноСборке, ВидноНаследникам, ВидноНаследникамСборки - атрибуты видимости классов и их членов;

ПространствоИмен("МоёПространство "), ПространствоИмён("МоёПространство") (синонимы) - атрибут класса, определяющий пространство имен, к которому принадлежит класс;

ОднопоточнаяМодель, МногопоточнаяМодель - атрибуты метода Старт, определяющие модель взаимодействия для COM объектов;

ОбщийДляКласса - атрибут члена класса (поля, метода, свойства или события) делающий его общим для всех созданных экземпляров этого класса;

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

Сериализуемый, НеСериализуемый – атрибуты класса, указывающие компилятору необходимость создать код поддержки сериализации данных класса или не возможность его сериализации;

ДолженНаследоваться, МожетНаследоваться, НеМожетНаследоваться - атрибуты класса, определяющие возможность или необходимость его наследования;

ДолженПереопределяться, МожетПереопределяться, НеМожетПереопределяться - атрибуты члена класса, определяющие возможность или необходимость его переопределения;

Переопределение - атрибут переопределения метода родителя в классе-наследнике;

Перекрытие - атрибут перекрытия метода родителя в классе-наследнике;

Перегрузка - атрибут перегрузки методов с одинаковыми именами;

ТолькоЧтение, ТолькоЗапись - атрибуты ограничения доступа к полям и свойствам;

Обработчик("МоёСобытие") - атрибут метода класса (процедуры), определяющий, что метод является обработчиком указанного события;

ИмпортМетода – специальный атрибут метода, указывающий компилятору, что реализация метода находится во внешней библиотеке и имеет указанную сигнатуру;

Устаревший("Этот элемент устарел!") – специальный атрибут, указывающий пользователям программы, что этот элемент устарел;

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

РасширяетТип, СужаетТип– атрибуты оператора ЗнчКТипу, указывающие компилятору, будет ли в процессе преобразования значения из одного типа в другой происходить потеря данных или точности значения;

Флаги – специальный атрибут перечисления, указывающий компилятору, что каждое значение перечисления интерпретируется как набор битовых флагов. Например, в значении 0b0010 установлен флаг во втором разряде (единица);

Реализует("ПолноеИмяЧленаИнтерфейса") – специальный атрибут члена класса, указывающий компилятору, что этот член реализует член указанного интерфейса;

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

 

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

 

Атрибуты сборки.

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

АтрибутСборки   System.Runtime.InteropServices.ComVisible(Ложь)

С оператором АтрибутСборки можно использовать не только атрибуты, определенные в Net, но и созданные вами атрибуты, если в дальнейшем Вы захотите получать дополнительную информацию о сборке.

 

Атрибуты модуля сборки.

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

АтрибутМодуля   System.CLSCompliant(Истина)

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

 

Атрибуты параметров метода.

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

&ВидноВсем
Функция СобратьБит32( &АнглСиноним("HighDigits") Знач СтаршиеРазряды тип Бит16,
                      &АнглСиноним("LowDigits")  Знач МладшиеРазряды тип Бит16
                      ) &АнглСиноним("ReturnValue") тип Бит32 //к возвращаемому параметру тоже можно применить атрибуты
    Возврат (Бит32(СтаршиеРазряды) << 16) БитИли МладшиеРазряды
КонецФункции

 

Определение особого порядка и правил передачи полей структуры.

Структуры, которые необходимо передавать коду, написанному на языках подобных C, C++, Rust, чаще всего необходимо отметить атрибутом StructLayout заставляющем среду исполнения сформировать структуру пригодную к передаче. Также необходимо убедиться, что правильно передаются поля имеющие сложный тип, такие как массивы или другие структуры. Для задания правил передачи используется атрибут MarshalAs. Ознакомьтесь с документацией .Net по этим атрибутам, прежде, чем передавать структуры в код, написанный на указанных языках.

&StructLayout(LayoutKind.Sequential){ .Pack=1, .CharSet=CharSet.Auto }
Структура UDT
    &ВидноВсем Поле rxStatus тип Цел16
    &ВидноВсем Поле datalen тип Байт

    &ВидноВсем, MarshalAs(UnmanagedType.ByValArray){ .SizeConst=255 }
    Поле array1 тип Байт[]

    &ВидноВсем
    Процедура Инициализировать()
        //код инициализации
    КонецПроцедуры

КонецСтруктуры

 

Некоторые случаи применения атрибутов в Net.

1. Пометить метод атрибутом System.Web.Services.WebMethod в Web сервисах, для указания, что метод должен вызываться через SOAP протокол.

2. Описание способа передачи параметров метода в не управляемый код с помощью атрибута System.Runtime.InteropServices.MarshalAs.

3. Описание свойств COM для классов, методов и интерфейсов с помощью группы атрибутов подобных System.Runtime.InteropServices.ComVisible или System.Runtime.InteropServices.DispId.

4. Вызов методов неуправляемого кода с помощью атрибута System.Runtime.InteropServices.DllImport (синоним ИмпортМетода).

5. Описание свойств сборки, таких как, версия, заголовок, копирайт и т.д., с помощью группы атрибутов подобных System.Reflection.AssemblyTitle.

6. Пометка членов класса, которые могут быть сериализованы с помощью атрибута System.Serializable (синоним Сериализуемый).

7. Описание сопоставления между членами класса и узлами XML для сериализации объекта в XML.

8. Описание требований безопасности для методов.

9. Указание характеристик, используемых для обеспечения безопасности.

10. Установка параметров JIT компиляции, например, для сохранения удобства отладки.

11. Получение информации о вызывающем методе.

12. Указание на то, что метод или другой элемент программы устарел с помощью атрибута System.Obsolete (синоним Устаревший).

Использование атрибутов в указанных случаях описано в документации .Net.

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

 

Вывод: Атрибуты нужны, чтобы привязать к сборке, к модулю сборки, к элементам программы, к членам классов или параметрам методов дополнительную информацию, которую можно будет использовать на этапе компиляции или на этапе выполнения программы. Атрибут — это класс, унаследованный от типа Атрибут. Информация, заданная через конструктор атрибута, сохраняется в метаданных сборки и может быть извлечена в любое время вашей программой или любой другой программой, которая использует или исследует сборку.

 

 




К началу статьи


Предыдущая статья:
Оператор Попытка. Структурная обработка ошибок.

Следующая статья:
Оператор Использовать - гарантированное завершение объекта

Вернуться в раздел:
Синтаксис языка Перфолента
  Поддержи проект!

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

  Новости:
      04.01.2025 Опубликован новый релиз дистрибутива языка программирования Перфолента.Net версии 0.4.15.0_CE
      23.09.2024 Опубликована новая статья: "Конструируем класс. Делегаты."
      30.08.2024 Опубликован новый релиз дистрибутива языка программирования Перфолента.Net версии 0.4.14.0
      24.05.2024 Обновлён справочный раздел сайта
      01.07.2023 Новая версия 0.4.13.0 языка программирования Перфолента.Net
       Все новости